1
votes

My parent component shows an error about my props:

Warning: Failed prop type: The prop prop name here is marked as required in ParentComponent, but its value is undefined.

The values are not undefined though.

When I remove isRequired from my PropTypes I get the error:

'Type Error: this.state is undefined'

But again my state is defined above.

I am new to react and javascript in general, any help is appreciated :)

I thought maybe it was because I was using arrow functions, so i switched to regular functions and bind them in the constructor but that didn't work. The code worked when it wasn't separated into components like it is now. What am I doing wrong here guys?

import PropTypes from 'prop-types';
import apiKey from '../config/apiKey'
import SearchForm from './SearchForm'
import SearchResults from './SearchResults'
import Details from './Details'

class ParentComponent extends React.Component {
    constructor(props) {
        super(props)

        this.state = {
            term: '',
            location: '',
            isLoading: false,
            businesses: [],
            business: {}
        }

    }

    handleChange = (event) => {
        const { name, value } = event.target;

        this.setState({
            [name]: value
        })
    }

    // Get data based on search term and location
    handleSubmit = (event) => {
        event.preventDefault();

        const term = this.state.term;
        const location = this.state.location;

        this.setState({
            isLoading: true
        });

        fetch(`https://cors-anywhere.herokuapp.com/https://api.yelp.com/v3/businesses/search?term=${term}&location=${location}`,
            {
                headers: { 'Authorization': `Bearer ${apiKey}` }
            })
            .then(response => response.json())
            .then(response => {

                const Businesses = response.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.title,
                        rating: business.rating,
                        reviewCount: business.review_count
                    }
                });

                return this.setState({
                    businesses: Businesses,
                    isLoading: false
                });
            })
            .catch(err => console.log(err))
    };

    BusinessList = this.state.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.title,
            rating: business.rating,
            reviewCount: business.review_count
        }
    })

    // Get detail data from business based on id extracted from previous fetch request
    getDetails = () => {
        return fetch(`https://cors-anywhere.herokuapp.com/https://api.yelp.com/v3/businesses/${this.BusinessList.id}`,
            {
                headers: { 'Authorization': `Bearer ${apiKey}` }
            })
            .then(response => response.json())
            .then(response => {
                const data = {
                    id: response.id,
                    alias: response.alias,
                    name: response.name
                }
                this.setState({
                    business: data
                });
            })
            .catch(err => console.log(err))
    };

    render() {

        return (
            <div>
                <SearchForm
                    handleSubmit={this.handleSubmit}
                    handleChange={this.handleChange}
                    term={this.state.term}
                    location={this.state.location}
                />

                <SearchResults
                    key={this.BusinessList.id}
                    id={this.BusinessList.id}
                    imageSrc={this.BusinessList.imageSrc}
                    name={this.BusinessList.name}
                    address={this.BusinessList.address}
                    city={this.BusinessList.city}
                    state={this.BusinessList.city}
                    zipCode={this.BusinessList.zipCode}
                    category={this.BusinessList.category}
                    rating={this.BusinessList.rating}
                    reviewCount={this.BusinessList.reviewCount}
                />

                <Details
                    key={this.business.id}
                    id={this.business.id}
                    alias={this.business.alias}
                    name={this.business.name}
                />
            </div>
        );
    };
};

ParentComponent.propTypes = {
    term: PropTypes.string.isRequired,
    location: PropTypes.string.isRequired,
    isLoading: PropTypes.bool.isRequired,
    businesses: PropTypes.array.isRequired,
    business: PropTypes.object.isRequired
}

export default ParentComponent;
1
Please post code when you separated them.mukesh210

1 Answers

0
votes

PropTypes are used for props that are passed down to the component and not for the state variables in the component.

ParentComponent.propTypes = {
    term: PropTypes.string.isRequired,
    location: PropTypes.string.isRequired,
    isLoading: PropTypes.bool.isRequired,
    businesses: PropTypes.array.isRequired,
    business: PropTypes.object.isRequired
}

When you do this, React thinks that term, location, isLoading, businesses and business are passed as props to the ParentComponent. But I see that they are all just state variables.

To understand better, take this case:

<Details
      key={this.business.id}
      id={this.business.id}
      alias={this.business.alias}
      name={this.business.name}
/>

You can add key, id, alias, name as PropTypes for Details component.