Search code examples
reactjsgetresponseaxios

How to get axios response properly in react?


I am trying to fetch data with axios for a search bar functionality, but I can't have it working. When I console log de reponse IN the searchForPlaces function below I get the reponse, however I get undefined when i call it in my App.

Here is my function to get data, which is located in my utils.js:

export function searchForPlaces(dataToSearch) {
  const requestUrl = `https://api.mapbox.com/geocoding/v5/mapbox.places/${dataToSearch}.json?access_token=${accessToken}`;

  const result = axios
    .get(requestUrl)
    .then(response => {
      return response;
    })
    .catch(error => {
      return error;
    });
}

Here is the code:

class App extends React.Component {
  renderSearchedPlaces() {
    console.log("render");
    return (
      <div>
        {this.state.searchForPlacesResponse.data.features.forEach(place => {
          return <div>{place}</div>;
        })}
      </div>
    );
  }

  querySearchForPlaces() {
    this.searchInputTimeout ? clearTimeout(this.searchInputTimeout) : null;

    console.log(searchForPlaces(this.state.searchInputValue));
    this.searchInputTimeout = setTimeout(
      function() {
        let searchForPlacesResponse = searchForPlaces(
          this.state.searchInputValue
        );

        this.setState({ searchForPlacesResponse });
      }.bind(this),
      400
    );
  }

  renderContent(item) {
    if (item === "share") {
      return (
        <React.Fragment>
          <h2>
            Share with your friends the places that you like(d), or
            dislike(d)...
          </h2>
          <div className="search-nearby">
            <div
              className={
                this.state.searchNearby === "search"
                  ? "search selected"
                  : "search"
              }
              onClick={() => {
                this.state.searchNearby === "search"
                  ? null
                  : this.setState({ searchNearby: "search" });
              }}
            >
              Search
            </div>
            <div
              className={
                this.state.searchNearby === "nearby"
                  ? "nearby selected"
                  : "nearby"
              }
              onClick={() => {
                this.state.searchNearby === "nearby"
                  ? null
                  : this.setState({ searchNearby: "nearby" });
              }}
            >
              Nearby
            </div>
          </div>
          <input
            className="search-input"
            type="text"
            placeholder="Search a place"
            value={this.state.searchInputValue}
            onChange={e => this.setState({ searchInputValue: e.target.value })}
            onKeyUp={() => this.querySearchForPlaces()}
          />
          {this.state.searchForPlacesResponse
            ? this.renderSearchedPlaces()
            : null}
        </React.Fragment>
      );
    }
  }

  // ...
}

Solution

  • The axios request is asynchronous, so your searchForPlacesResponse will be undefined.

    You can instead return the axios request, and use then in querySearchForPlaces to wait for the promise to resolve before using setState.

    export function searchForPlaces(dataToSearch) {
      const requestUrl = `https://api.mapbox.com/geocoding/v5/mapbox.places/${dataToSearch}.json?access_token=${accessToken}`;
    
      return axios
        .get(requestUrl)
        .then(response => {
          return response.data;
        })
        .catch(error => {
          console.error(error);
        });
    }
    
    class App extends React.Component {
      // ...
    
      querySearchForPlaces() {
        this.searchInputTimeout ? clearTimeout(this.searchInputTimeout) : null;
    
        console.log(searchForPlaces(this.state.searchInputValue));
        this.searchInputTimeout = setTimeout(() => {
          searchForPlaces(this.state.searchInputValue)
            .then(searchForPlacesResponse => {
              this.setState({ searchForPlacesResponse });
            });
        }, 400);
      }
    
      // ...
    }