Ravenous Part 4 Error Help!

The problem I’m having on this project is that as soon as I type something in the “Search Businesses” area, the TypeError pops up.
This is my code for SearchBar.js:

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

class SearchBar extends React.Component {

    constructor(props){
        super(props);
        this.state = { /*initial state of SearchBar*/
            term:'',
            location:'',
            sortBy:'best-match'
        }; 
        /*Using Yelp API*/
        this.sortByOptions = {
            'Best Match': 'best_match', /*The Default*/
            'Highest Rated': 'rating',
            'Most Reviewed': 'review_count'
        };
        this.handleTermChange=this.handleTermChange.bind(this);
        this.handleLocationChange=this.handleLocationChange.bind(this);
        this.handleSearch=this.handleSearch.bind(this);
    }

    /* Provides visual feedback to users */
    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(); /* Prevents the (anchor tag) default of clicking a link at the end of a method */
    }

    /*Creates List Items Needed to Display the Sorting Options*/
    renderSortByOptions() {
        return Object.keys(this.sortByOptions).map(sortByOption => {
            
            /*sortByOption = the sortByOptions keys*/
            let sortByOptionValue = this.sortByOptions[sortByOption];
            return (<li 
                    key={sortByOptionValue} 
                    className={this.getSortByClass(sortByOptionValue)} 
                    onClick={this.handleSortByChange.bind(this,sortByOptionValue)}>
                        {sortByOption}
            </li>);
        });
    
    };

    render() {
        return (
            /*Code Generally Given by Codecademy*/
            <div className="SearchBar">
            <div className="SearchBar-sort-options">
                <ul>
                    {this.renderSortByOptions()} 
                </ul>
            </div>
            <div className="SearchBar-fields">
                <input placeholder="Search Businesses" onChange={this.handleSortByChange}/>
                <input placeholder="Where?" onChange={this.handleLocationChange}/>
            </div>
            <div className="SearchBar-submit">
                <a href="www.#.com" onClick={this.handleSearch}>Let's Go</a>
            </div>
            </div>
        );
    };
};


export default SearchBar;

Could someone please help me figure out how to fix this issue? Thanks!

Also there happens to be this “;” in the business list area that I can’t seem to find in my code but appears when i run the project. Any idea of where this semicolon might come from? Trying to get rid of it.

Hi there!

You might have more luck posting in the Javascript/React specific category for help. I just happened across your topic while exploring the forums. Just trying to set you up for success! :wink:

Back to your code, off the bat, it looks like you have a typo in the constructor. You have best-match, I think it should be best_match (at least that’s what I have). Also, I’m not sure you need the semicolons after your closing method brackets in the class. These should be separated by line breaks. But, this could be an optional thing…I’m still learning how strict react is and coming from strict JS back in the day. :wink:

sortBy:'**best-match**'

handleSortByChange(sortByOption){
        this.setState({
            sortBy: sortByOption
        });
    }; <---- Remove closing semicolons from the function closing brackets inside the class

Your first input for search businesses should handle the term change, not the sort change. This is if a new keyword is searched for, not changing the way it’s being sorted, if that makes sense.

<input placeholder="Search Businesses" onChange={**this.handleSortByChange**}/>

For your search button, remove 'href=“www.#.com”. This is not needed with the onClick setting as we execute the search via the API.

<a **href="www.#.com"** onClick={this.handleSearch}>Let's Go</a>

Hope this helps get you in the right direction! And of course, these are recommendations based on the code I can see.

1 Like

Thank you so much for finding those errors!!! It definitely helped me get a little closer to having a working program.

Removing the 'href=“www.#.com” resulted in the program to compile with warnings:

./src/components/SearchBar/SearchBar.js
  Line 87:  The href attribute is required for an anchor to be keyboard accessible. Provide a valid, navigable address as the href value. If you cannot provide an href, but still need the element to resemble a link, use a button and change it with appropriate styles. Learn more: https://github.com/evcohen/eslint-plugin-jsx-a11y/blob/master/docs/rules/anchor-is-valid.md  jsx-a11y/anchor-is-valid

Sadly after those changes were made, more errors came up that I can’t seem to fix :sweat_smile:. I’m checking my code with previous ravenous solutions and other people’s posts but i still can’t seem to find the issue.
I also still cannot find the problem to the random unwanted ‘;’ in the business list area.
Would you, or someone, happen to know what went wrong here?
Thanks!

BusinessList.js:

import React from 'react';
import './BusinessList.css';
import Business from '../Business/Business'; /*Importing the Business Component*/

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

export default BusinessList;

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);
  }
  /*simulating how a search would be like (will be replaced later) */
  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;

Thank you again for the help! i appreciate it a lot (-:

You bet! Debugging helps me understand the code. You’re helping me too!

Your BusinessList.js matches mine except for the semicolons. I only have one to close the return (); in the class.

return( /* Iterate through array and return Business components */
            <div className="BusinessList">
            {
                this.props.businesses.map(business => {
                    return <Business business={business} key={business.id}/>;
                })
            }; <--- remove
          </div>
        ); <--- keep
    }; <--- remove

In App.js your searchYelp looks a bit off with the closing }'s. I think you may have an extra set. Remove the ones around businesses. I suspect this is why your search isn’t working.

searchYelp(term, location, sortBy){
    Yelp.search(term, location, sortBy)
    .then(businesses => {
      this.setState({businesses: {businesses}}); <--- extra {} should be {businesses:  businesses } here
    });
  }

in Business.js, you might be doing it a bit differently and that’s ok! I’m still learning too and props are not my strongest, but this is what I see:

class Business extends React.Component {
    render(){
        const {business} = this.props; <-- I'm not sure this does what you want, but I see this as trying to eliminate repetition. I do not have this in my code. That doesn't mean it's wrong though - just an observation. 
        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> <-- for each of the business items I have this.props so this would be {this.props.business.address} If you get the issue above working, you might not have to change this section. If not, I'd remove the above variable and add this.props to each item in this section. 
                    <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>
        );
    }
}; <-- remove this, but again... not sure it matters. 

Let me know how it goes!

1 Like

oh my GOSH thank you so much! :star_struck:

Both of the problems I had are gone!
I didn’t have to change anything in Business.js, but the changes you recommended with BusinessList.js and App.js helped fix everything!

Deleting the ; in between the divs eliminated the random ‘;’.
Deleting the extra {} helped the errors go away!

Thank you for all your help!!!
I really appreciate it.

1 Like

Excellent news! Happy to help! And thanks for letting me know what fixed the issue.