1

I have a component that works and will return data from State as long as it isn't nested. However, if I need to dig a little deeper within the object, I get an error: "TypeError: Cannot read property 'name' of undefined".

I'm positive that there is a value for it (checked Inspector and the variable does indeed have a value, that's how I knew what to put in code). Why does it work for a higher value, but not the lower value?

class Concert extends Component {

constructor(props) {
    super(props);

    this.state = ({
        concert:''
    })
}
componentDidMount(){
    var concertid = `${REQ_URL}/${this.props.match.params.concertid}`;
    fetch(concertid, {
        method: 'GET'
    })
    .then(response => response.json())
    .then(json => {
        this.setState({
            concert:json
        })
    })


}
render() {
    return (
        <div>
            <Header />
            <div className="concert">
                <div className="venue">

                //THIS IS THE PART THAT RETURNS ERROR
                //this.state.concert.id returns a correct value
                //POSITIVE this.state.concert.artist.name DOES CONTAIN VALUE

                Venue: {this.state.concert.artist.name}
                </div>

            </div>
        </div>
        )
}

}

3 Answers 3

4

When the component is rendered for the first time, the value of this.state.concert is '' (you set that value in the constructor) so if you are trying to access this.state.concert.artist.name you are actually trying to access undefined.name - and there is your error.

The value of this.state.concert is getting change only after the component was loaded - after the success callback of your fetch call is done, and only then that value will be available.

What you can do is check if you have a value before accessing it:

{this.state.concert && this.state.concert.artist &&
    <div>Venue: {this.state.concert.artist.name}</div>
}       
Sign up to request clarification or add additional context in comments.

2 Comments

Indeed it is undefined, but so is this.state.concert.id at the time and it renders correctly. Why does one work, but not the other though? You fix did work correctly btw.
Beause you access this.state.concert.id and not this.state.concert.SOMETHING.id. Concert is available (it's an empty string), so concert.id is undefined, which is not an error.
3

easy, api calls are asynchronous so this.state.concert.artist.name will be {"empty"} until you get the api response.

use this:

Venue: {this.state.concert && this.state.concert.artist && this.state.concert.artist.name}

1 Comment

I like this suggestion.
1

The problem is it's trying to render before the data is there since the API call is asynchronous.

A nicer way to fix this is to extract the values using es6 object destructuring with defaults:

const {
  id,
  artist: {
    name
  } = {}
} = this.state.concert;

-

Venue: {name}

This way, if artist is not present you'll just get undefined instead of throwing an error

Also concert should be an object by default in the constructor:

this.state = {
    concert: {}
};

1 Comment

Thanks for the idea. The only issue with that is that the 'concert' object is pretty large so setting up the const would take a while.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.