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;

Hello!

I’m running through the exact same issue with my code. I’m getting a

Unhandled Rejection (TypeError): Cannot read property ‘map’ of undefined

BusinessList.render
src/components/BusinessList/BusinessList.js:8

I’ve tried to look into my searchBar,js to find an anomaly, but I couldn’t find anything relevant…
Also, up to the end of Ravenous part 3, everything was working fine, and searchBar seemed to function well.
Just to be sure, I’ve tried to replace my searchBar.js code with the code provided by nungon above, but I’d get the same error again…

I’ll past the code of my searchBar.js file as well as my App.js and BusinessList.js as those seem to be related to the problem somehow…

For searchBar.js

import React from 'react';
import './SearchBar.css';
 
class SearchBar extends React.Component{
     constructor(props){
         super(props);
         this.state = {
             term:'',
             location:'',
             sortBy:'best_match'
         };
         this.handleTermChange = this.handleTermChange.bind(this);
         this.handleLocationChange = this.handleLocationChange.bind(this);
         this.handleSearch = this.handleSearch.bind(this);
         this.sortByOptions = {
             'Best Match': 'best_match',
             'Highest Rated': 'rating',
             'Most Reviewed': 'review_count'
         };
     }
     getSortByClass(sortByOption){
 if(this.state.sortBy === sortByOption){
     return 'active';
 }return '';
 };
     handleSortByChange(sortByOption){
 this.setState({
     sortBy: sortByOption
 });
     }
     handleTermChange(event) {
 this.setState({term: event.target.value});
     }
     handleLocationChange(event){
 this.setState({location: event.target.value});
     }
     handleSearch(event){
 this.props.searchYelp(this.state.term,this.state.location,this.state.sortBy);
     event.preventDefault();
 }
 
     renderSortByOptions(){
         return Object.keys(this.sortByOptions).map(sortByOption=>{
 var sortByOptionValue = this.sortByOptions[sortByOption];
 return <li className={this.getSortByClass(sortByOptionValue)} onClick={this.handleSortByChange.bind(this,sortByOptionValue)} key={sortByOptionValue}>{sortByOption}</li>
         })
     }
 render(){
     return (
         <div className="SearchBar">
   <div className="SearchBar-sort-options">
     <ul>
       {this.renderSortByOptions()}
     </ul>
   </div>
   <div className="SearchBar-fields">
     <input placeholder="Search Businesses" onChange={this.handleTermChange}/>
     <input placeholder="Where?" onChange={this.handleLocationChange}/>
   </div>
   <div className="SearchBar-submit">
     <a onClick={this.handleSearch}>Let's Go</a>
   </div>
 </div>
     )
 }
 }
 
 export default SearchBar;

for App.js

 import React from 'react';
 import './App.css';
 import BusinessList from '../BusinessList/BusinessList';
 import SearchBar from '../SearchBar/SearchBar';
 import Yelp from '../../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.search(term,location,sortBy).then((businesses)=>{
   this.setState({businesses: businesses});
   })
 }
   render(){
     return (
       <div className="App">
   <h1>ravenous</h1>
   <SearchBar searchYelp={this.searchYelp}/>
   <BusinessList businesses={this.state.businesses}/>
 </div>
       );
   }
   
     
   
 }

export default App;

For BusinessList.js

 import React from 'react';
 import './BusinessList.css';
 import Business from '../Business/Business';
 
 class BusinessList extends React.Component{
     render(){
         return(
             <div className="BusinessList">
 {this.props.businesses.map(business=>
     {return <Business business={business} key={business.id}/>}
 )
     };
 
 </div>
         );
 };
 };
 
 export default BusinessList;

I would really be thankful if someone could help me figure out what’s wrong with my code…

Thanks a lot!

I update this thread as I’ve found where my error came from, maybe it can help some people.

In step 18’s hint of the ravenous project part 4, the following code is given:

return jsonResponse.businesses.map(business => {

});

it is asked that the callback function returns an object, but according to the Mozilla developer resource website,

// Parenthesize the body of a function to return an object literal expression:
params => ({foo: bar})

Once I updated that in my code, the error was gone and it functioned perfectly.

I found this while comparing the solution code given in the next lesson with my code, and looking on google why the callback function on map had () right after the => (answer=because the callback function returns an object)

1 Like

I am having this exact same problem - only putting those brackets in doesn’t solve the problem for me. If I put in my code any help would be appreciated - I’ve been looking at it for a very long time now!!

App.js

import React from 'react';
import './App.css';

import BusinessList from '../BusinessList/BusinessList';
import SearchBar from '../SearchBar/SearchBar';
import Yelp from '../../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.search(term, location, sortBy).then(businesses =>{
      this.setState({businesses: businesses});
    });
  }


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

export default App;

Business.js

import React from 'react';
import './Business.css';

class Business extends React.Component {
  render (){
    return (
      <div className="Business">
        <div className="image-container">
          <img src={this.props.business.imageSrc} alt=''/>
        </div>
        <h2>{this.props.business.name}</h2>
        <div className="Business-information">
          <div className="Business-address">
            <p>{this.props.business.address}</p>
            <p>{this.props.business.city}</p>
            <p>{`${this.props.business.state} ${this.props.business.zipCode}`}`</p>
        </div>
        <div className="Business-reviews">
          <h3>{this.props.business.category}</h3>
          <h3 className="rating">{`${this.props.business.rating} stars`}</h3>
          <p>{`${this.props.business.reviewCount} reviews`}</p>
        </div>
      </div>
    </div>
    );
  }
}


export default Business;

BusinessList.js

import React from 'react';
import './BusinessList.css';
import Business from '../Business/Business';

class BusinessList extends React.Component {
  render (){
    return (
      <div className="BusinessList">
      {
        this.props.businesses.map(business => {
        return <Business business={business} key={business.id} />
      })
    }
     </div>
    );
  }
}

export default BusinessList;

searchBar.js

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

class SearchBar extends React.Component {
  constructor(props) {
    super(props);

    this.state = {
      term: '',
      location: '',
      sortBy: 'best_match'
    };

    this.handleTermChange = this.handleTermChange.bind(this);
    this.handleLocationChange = this.handleLocationChange.bind(this);
    this.handleSearch = this.handleSearch.bind(this);
    this.handleSortByChange = this.handleSortByChange.bind(this);

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

  getSortByClass(sortByOption){
    if (this.state.sortBy === sortByOption){
      return 'active';
     }
        return '';
    }

    handleSortByChange(sortByOption){
      this.setState({sortBy: sortByOption});
    }

    handleTermChange(event){
      this.setState({term: event.target.value});
    }

    handleLocationChange(event){
      this.setState({location: event.target.value});
    }

    handleSearch(event){
      this.props.searchYelp(this.state.term, this.state.location, this.state.sortBy);
      event.preventDefault();
    }


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


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

export default SearchBar;

Yelp.js

const apiKey = '';



const Yelp = {
  search(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 => ({
        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.zip_code,
        category: business.title,
        rating: business.rating,
        reviewCount: business.review_count}
      ));
      }
    });
  }
};

export default Yelp;

I would be sooo happy if I could get this thing to work - so many thanks in advance for any help!!

Hi!

Sorry if you have already tried, but in the code you have pasted above, in your BusinessList.js file,
I don’t see the () wrapping up the object returned by the arrow function.
Instead of:

this.props.businesses.map(business => {
        return <Business business={business} key={business.id} />
      })

you should have:

this.props.businesses.map(business => ({
        return <Business business={business} key={business.id} />
      }))

Hope this helps!

Hello!
Many thanks for your help.
Unfortunately putting these brackets in only gave another error.
I now have put the solution code in to see if that works - but it gives the same error as I had before so I think I’m going to have to give up on this one. Shame as I’ve put in a lot of time on it.
So frustrating!