Ravenous Part 4 Cannot Read Property Map of Undefined

I have checked my syntax a million times and cannot find any mistake. My application is fine until I click ‘Lets Go’. I checked the console I get a 400 error:

Failed to load resource: the server responded with a status of 400 (Bad Request)

and

Uncaught TypeError: Cannot read property 'map' of undefined: BusinessList.js:8

App.js:

import React from 'react';
import './App.css';
import BusinessList from './components/BusinessList/BusinessList';
import SearchBar from './components/SearchBar/SearchBar';
import Yelp from '../src/util/Yelp';

class App extends React.Component {

  constructor(props) {
    super(props);
    this.state = {
      businesses: []
    }
    this.searchYelp = this.searchYelp.bind(this);  
  }

  searchYelp(term, location, sortBy) {
    Yelp.searchYelp(term, location, sortBy).then((businesses) => {
      this.setState({
        businesses: businesses
      })
    });
  }

  render() {
    return (
      <div className="App">
        <div className="App">
          <h1>ravenous</h1>
          <SearchBar searchYelp={this.searchYelp} />
          <BusinessList businesses={this.state.businesses} /> 
        </div>
      </div>
    );
  }
}
export default App;

BusinessList.js:

import React, { Component } from 'react';
import './BusinessList.css';
import Business from '../Business/Business';

class BusinessList extends Component {
    render() {
        return(
            <div className='business-list'>
                { this.props.businesses.map(business => {
                        return <Business key={business.id} business={business} />
                    })}
            </div>
        );
    }
}
export default BusinessList;

Yelp.js:

const apiKey = 'HeEf5ujS52b8UhWBh0s9HcdGSWa7byiM20dPoSPgf1qT-JYB-J0VNl62ZpyRrFFhbOry2j20EDxmKiJ0sfQ9FEWR6mNl4ybHHBh-4ttcdVkHngrrTE4jYmZ9B9fjXHYx';

const Yelp = {
    searchYelp(term, location, sortBy) {
        return fetch(`https://cors-anywhere.herokuapp.com/https://api.yelp.com/v3/businesses/search?term=${term}&location=${location}&sort_by=${sortBy}`, {
            headers: {
                Authorization: `Bearer ${apiKey}`,
            },
        }).then((response) => {
            return response.json();
        }).then((jsonResponse) => {
            if (jsonResponse.businesses) {
                return jsonResponse.businesses.map(((business) => {
                    return {
                        id: business.id,
                        imageSrc: business.image_url,
                        name: business.name,
                        address: business.location.address1,
                        city: business.location.city,
                        state: business.location.state,
                        zipCode: business.location.zipCode,
                        category: business.categories[0].title,
                        rating: business.rating,
                        reviewCount: business.review_count
                    };
                }));
            }
        })
    }
}
export default Yelp;

A lollipop to anyone who can solve it! :slight_smile:

I see a few small issues, but nothing to cause the problem you have. The issues I see will only cause issues with how the content is displayed. Here they are:
In App.js:

      <div className="App"> <!--Double <div> Not really detrimental. Just unnecessary.-->
        <div className="App"> <!--Double div-->
          <h1>ravenous</h1>
          <SearchBar searchYelp={this.searchYelp} />
          <BusinessList businesses={this.state.businesses} /> 
        </div>
      </div>

In BusinessList.js:

        return(
            <div className='business-list'> <!--Should be 'BusinessList' to get proper css styling -->
                { this.props.businesses.map(business => {
                        return <Business key={business.id} business={business} />
                    })}
            </div>
        );

In Yelp.js:

                    return {
                        id: business.id,
                        imageSrc: business.image_url,
                        name: business.name,
                        address: business.location.address1,
                        city: business.location.city,
                        state: business.location.state,
                        zipCode: business.location.zipCode, <!--This should be .zip_code-->
                        category: business.categories[0].title,
                        rating: business.rating,
                        reviewCount: business.review_count
                    };

Possibly the problem causing the error is in Business.js? Hope this helps a little.

1 Like

Update: I commented out my own code, and replaced it with the code you have supplied. It worked as expected. No errors. Could you provide Business.js and SearchBar.js?

2 Likes

Same here, the code worked fine. Spotted to many parentisis on the second to last return of Yelp.js. I guess the problem must be in SearchBar.js.

1 Like

It’s solved! The problem was lying in SearchBar.js like you said. Thanks for the help :slight_smile:

2 Likes

Hii harry i am also getting same error.can you give me search.js file

Please give me search .js

Please give me search bar .js file

Hope it helps:

import React from "react";
import "./SearchBar.css";


class SearchBar extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      term: "",
      location: "",
      sortBy: "best_match"

    };
    this.sortByOptions = {
      "Best Match": "best_match",
      "Highest Rated": "rating",
      "Most Reviewed": "review_count"
    };
  }

  getSortByClass(sortByOption) {
    if (this.state.sortBy === sortByOption) {
      return "active";
    } 
    return "";
    //this.state.sortBy === sortByOption ? "active" : ""; -> raises ESLint error, can be fixed w/ if/else statement or disabling no-unused-expressions
  }

  handleSortByChange = (sortByOption) => {
    this.props.searchYelp(this.state.term, this.state.location, sortByOption);
    this.setState({sortBy: sortByOption});
  }

  handleTermChange = (e) => {
    this.setState({term: e.target.value});
  }

  handleLocationChange = (e) => {
    this.setState({location: e.target.value});
  }

  handleSearchClick = (e) => {
    this.props.searchYelp(this.state.term, this.state.location, this.state.sortBy);
    e.preventDefault(); //to prevent the default action of clicking a link from triggering at the end of the method
  }

  handleSearchEnter = (e) => {
    if (e.key === "Enter") {
      this.props.searchYelp(this.state.term, this.state.location, this.state.sortBy);
      e.preventDefault();
    }
  }

  renderSortByOptions = () => {
    return Object.keys(this.sortByOptions).map(sortByOption => {
      let sortByOptionValue = this.sortByOptions[sortByOption];
      return <li key={sortByOptionValue} onClick={this.handleSortByChange.bind(this, sortByOptionValue)} className={this.getSortByClass(sortByOptionValue)}>{sortByOption}</li>
    });
  }

  render() {
    return (
      <div className="SearchBar" onKeyPress={this.handleSearchEnter}>
        <div className="SearchBar-sort-options">
          <ul>
            {this.renderSortByOptions()}
          </ul>
        </div>
        <div className="SearchBar-fields">
          <input onChange={this.handleTermChange} placeholder="Search Businesses" />
          <input onChange={this.handleLocationChange} placeholder="Where?" />
        </div>
        <div className="SearchBar-submit">
          <a onClick={this.handleSearchClick} href="foo" >Let's Go</a>
        </div>
      </div>
    )
  }
}

export default SearchBar;