Ravenous Part 4 - debugging

https://www.codecademy.com/paths/web-development/tracks/front-end-applications-with-react/modules/ravenous-part-four/projects/interacting-with-yelp-api

Not sure why I’m getting this error code!

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

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

export default BusinessList;
1 Like

Hello, @method6453649862. Welcome to the forums.

So, the error message says, cannot read property 'map' of undefined. Where are you using ‘map’?

The message is saying that the object that you are trying to access the ‘map’ property of is undefined, so we need to look at where it was supposed to be defined, and determine why it isn’t.

I am using the map function in my BusinessList component

I followed the example videos exactly so I’m not sure why I’m getting this error

This is my App component where businesses is being rendered

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= {
      business: [],
    };

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

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

export default App;
1 Like

Okay, so what is the name of the object that is undefined? Does the object exist? (Is it defined?)
If we look at the line of code where you try to access ‘map’:

this.props.businesses.map(function(business, i)

Then we look at the props in your App component:

class App extends React.Component {
  constructor(props) {
    super(props);
    this.state= {
      business: [],
    };

Is there a prop named businesses? :wink:

There is another issue here:

I made some changes, but still no fix. It must be something small that I can’t see. I feel like I have combed over everything multiple times!

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 = {
      business: [],
    };

    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">
        <h1>ravenous</h1>
        <SearchBar searchYelp={this.searchYelp} />
        <BusinessList businesses={this.state.businesses} />
      </div>
    );
  }
}

export default App;

Yelp.js

const apiKey='MJhN1iVFiA__KzcBk6LhC7jnnhKAMEjbJw7z7OOthxb7J34RfPztfGWKfm1Uxrl-g0w-DW8sNjZTw1xux0tCwCANqPIYbABPOpuCTFYc-5ZW59lmCPGnxWMZ3_hPXnYx';

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.zip_code,
                category: business.categories[0].title,
                rating: business.rating,
                reviewCount: business.review_count
              };
            });
          }
        });
    }
  };
  
  export default Yelp;

Business.js


class Business extends React.Component {
    render() {
        return (
            <div className="Business">
                <div className="image-container">
                    <img src={this.props.business.imageSrc} alt={this.props.business.name}/>
                </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 key={business.id} business={business}  />
          })
          )}
      </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.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;

I am also getting this error in my index.js

This still isn’t corrected.


class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      business: [], //should be businesses
    };

Beyond that will have to wait till I have more time.

Oh I see. Thank you, it worked!

1 Like

@midlindner, I am getting the same issue referencing the same line of code (TypeError: Cannot read property ‘map’ of undefined) but my code matches the solution almost exactly and still not working. I don’t know where it is going wrong. Here is my error and code.

App.js
<import React from ‘react’;
//import logo from ‘…/…/…/src/logo.svg’;
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.searchYelp(term, location, sortBy).then((businesses) => {
this.setState({
businesses: this.businesses
});
});
}
render() {
return (


ravenous





);
}
}

export default App;

Business.js
<import React from ‘react’;
import ‘./Business.css’;
//import ReactDOM from ‘react-dom’;

class Business extends React.Component {
render () {
//const { business } = this.props;
return (





{this.props.business.name}




{this.props.business.address}


{this.props.business.city}


{this.props.business.state}, {this.props.business.zipCode}




{this.props.business.category.toUpperCase()}


{${this.props.business.rating} stars}


{${this.props.business.reviewCount} reviews}





);
}
}
export default Business;>

BusinessList.js
<import React from ‘react’;
import ‘./BusinessList.css’;
import Business from ‘…/Business/Business’;
class BusinessList extends React.Component {
render () {
return (


{
this.props.businesses.map(business => {
return
})
}

);
}
}
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';
    } else {
        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 key={sortByOptionValue} className={this.getSortByClass(sortByOptionValue)} onClick={this.handleSortByChange.bind(this, sortByOptionValue)}>{sortByOption}</li>);
    });
}
render () {
    return (
        <div className="SearchBar" searchYelp={this.searchYelp}>
            <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 = ‘y4WmFEnmPGfAzLsrT4d8jEMCEIMHeA3iTl13NlmUlZ7wAIepJd6GCQNorxDkL-lT8_LHgPXYkl6–ena7WIRcWFCmmnXcxBktvQOKeM9A06ymONUNF51QE6LHVcgX3Yx’

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 => ({
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.categories[0].title,
rating: business.rating,
reviewCount: business.review_count
}));
}
});
}
};
export default Yelp;>

The only difference from the solution is my searchYelp attribute on the SearchBar render method but removing it doesn’t do anything.

Please help! Thank you!

@midlindner, I am getting the same issue referencing the same line of code (TypeError: Cannot read property ‘map’ of undefined) but my code matches the solution almost exactly and still not working. I don’t know where it is going wrong. Here is my error and code.

App.js

import React from 'react';
//import logo from '../../../src/logo.svg';
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.searchYelp(term, location, sortBy).then((businesses) => {
      this.setState({
        businesses: this.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';
//import ReactDOM from 'react-dom';

class Business extends React.Component {
    render () {
        //const { business } = this.props;
        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.toUpperCase()}</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';
        } else {
            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 key={sortByOptionValue} className={this.getSortByClass(sortByOptionValue)} onClick={this.handleSortByChange.bind(this, sortByOptionValue)}>{sortByOption}</li>);
        });
    }
    render () {
        return (
            <div className="SearchBar" searchYelp={this.searchYelp}>
                <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 = 'y4WmFEnmPGfAzLsrT4d8jEMCEIMHeA3iTl13NlmUlZ7wAIepJd6GCQNorxDkL-lT8_LHgPXYkl6--ena7WIRcWFCmmnXcxBktvQOKeM9A06ymONUNF51QE6LHVcgX3Yx'

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 => ({
                        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.categories[0].title,
                        rating: business.rating,
                        reviewCount: business.review_count
                }));
            }
        });
    }
};
export default Yelp;

The only difference from the solution is my searchYelp attribute on the SearchBar render method but removing it doesn’t do anything.

Please help! Thank you!

Hello, @janeknapp3133885136, and welcome to the forums!
To find the source of the problem, we have to consider where the undefined thing was supposed to have been defined. What the computer currently sees is undefined.map(business => etc., so where do we look for where this.props.businesses should have been defined? That would be in our App.js file. We see it here:

So, if there were no modifications, we should at least be getting an empty array which would not throw the error you have. Therefore, we need to look for where businesses is modified, and that would be here:

So, what is this line of code doing that causes this.props.businesses to return undefined in the BusinessList.js file? I’ll give you a hint. What does this refer to in your code above? You may recall a little something from a previous lesson regarding using this within an arrow function.

We have an anonymous function with the parameter, businesses:

It is the array of businesses returned by the Yelp.searchYelp function. In the body of the anonymous arrow function, we are assigning that array as the property of the prop businesses. It’s confusing because they used the same name in the project. We need to assign the parameter businesses to the prop businesses using the setState method. You, however, are assigning undefined to the prop businesses because this.businesses does not refer to the function’s parameter.

Hopefully, some of that made sense.

Thank you! Changing it to the code below fixed it!

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