React 'Ravenous' Project

So I was on the final step for the Ravenous Project on the Website Development Career Path, and nearing the end of the project, the page’s search button won’t work and the list of pics and info won’t load. I’m not getting any errors, I’m working on Webstorm 2020.1.2, and I’m just looking for some help because I went through the whole code and couldn’t figure out whats going on. I know there is a lot of code plus the CSS and HTML files (those they gave me the code for), but if anyone could just help and tell me if there is any type of error, they would have my sincere gratitude. Here is the code that I worked on:
App.js:

import React from 'react';
import './App.css';
import SearchBar from "../components/SearchBar/searchBar";
import BusinessList from "../components/BusinessList/businessList";
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() {
        const business = this.props;
        return (
            <div className="Business">
                <div className="image-container">
                    <img src='https://s3.amazonaws.com/codecademy-content/programs/react/ravenous/pizza.jpg' alt='' />
                </div>
                <h2>{business.name}</h2>
                <div className="Business-information">
                    <div className="Business-address">
                        <p>{business.address}</p>
                        <p>{business.city}</p>
                        <p>{business.state} {business.zipCode}</p>
                    </div>
                    <div className="Business-reviews">
                        <h3>{business.category}</h3>
                        <h3 className="rating">{business.rating} stars</h3>
                        <p>{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';

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

class SearchBar extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
          term: '',
          location: '',
            sortBy: 'best_match'
        };
        this.getSortByClass = this.getSortByClass.bind(this);
        this.handleTermChange = this.handleTermChange.bind(this);
        this.handleLocationChange = this.handleLocationChange.bind(this);
        this.handleSearch = this.handleSearch.bind(this);

    }

    getSortByClass(sortByOption) {
        if (sortByOption === this.state.sortBy) {
            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(sortByOptions).map(sortByOption => {
            let sortByOptionValue = sortByOptions[sortByOption];
            return <li
                onClick={this.handleSortByChange.bind(this, sortByOptionValue)}
                className={this.getSortByClass(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 onChange={this.handleTermChange} placeholder="Search Businesses"/>
                    <input onChange={this.handleLocationChange} placeholder="Where?"/>
                </div>
                <div className="SearchBar-submit">
                    <a onClick={this.handleSearch}>Let's Go</a>
                </div>
            </div>
        )
    }
}

export default SearchBar;

Yelp.js

const apiKey = 'redacted';

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

export default Yelp;

Again, help would be greatly appreciated!

Hi there.

An immediate thing I noticed as wrong is the relative path to your Yelp.js file.

Your working tree (from the src directory) should look something like this:

src
├── components
│   ├── App
│   ├── Business
│   ├── BusinessList
│   └── SearchBar
└── util

so from the App folder, where App.js lives, you need to go up 2 directories before going down one level into util for Yelp.js.

I’ll take a look at come back if I spot anything else. :slight_smile:

Edit: I wouldn’t have done this line in Business.js this way:
const business = this.props;

If you wanted to shorten the typing elsewhere, you should probably have assigned this.props.business to const business rather than all the props as you have done. Won’t break anything, I don’t think, but I wouldn’t think it to be best practice either. :slight_smile:

Edit 2: Can’t see anything else in your code which is functionally different to how I did it… so I think it’s just your path which is wrong. :slight_smile:

Let us know if that doesn’t fix it. :slight_smile:

Capture1

This is what i saw on the web page when i removed const business = this.props;

And also on Webstorm (the app that I’m using to write the JSX and JavaScript) it told me that this is the correct file path:

import Yelp from ‘…/util/Yelp’

^^ 2 dots not 3

Idk what else I’m missing. And btw, thanks for reaching out and helping me!

Yes. I didn’t say remove it, though.

At the moment, you’re saving the entire props object to const business… which, in this case, is fine because it’s not a complex props… but if it were more complex that could get confusing quickly.

What I meant was you could change that line to const business = this.props.business so that the name of the constant reflects the prop you’re putting into it.

One of the early steps in the Ravenous project is to create the components directory, with the App subdirectory, and move the App.js and App.css files into it so that each component is in its own directory. The util directory which gets created later is meant, I think, to be on the same level as the components directory.

Don’t suppose there’s much chance of getting a screenshot or something of the folder structure you’ve set up? (Not sure if Webstorm shows it?)

Oh OK, I see now: “const business = this.props.business” instead of " const business = this.props".

And also here is a pic of the folder, “App” and “components” are 2 directories in the src directory:

This is the web page at the moment after the changes: