简体   繁体   中英

How to access elements in an Object which nested in an array of State in React?

I'm learning React, and today I encountered a problem. I tried to fetch data from an api, everything went well untill I changed the 'character' from an object to an array. After it, my jsx no longer could access elements from the state.

The snippet of the original code is as follow:

//When the state 'character' is an object

class Api extends React.Component {
    state = {
        loading: false,
        character: {}
    }

    componentDidMount() {
        this.setState({ loading: true });
        fetch('https://swapi.co/api/people/1')
            .then(response => response.json())
            .then(data => {
                this.setState(
                    {
                        character: data,
                        loading: false
                    }
                );
                console.log('newstate', this.state.character);
            });
    }
    render() {
        return (
    <div><h3>Name: {this.state.character.name}</h3>
            </div>
        )
    }

}

Later, I wanted to imporve the data structure, so I changed the 'character' state to an Array, according which I changed the way to access the 'character', turned out it's no longer works.

// after I changed the type of 'character'

class Api extends React.Component {
    state = {
        loading: false,
        character: []
    }

    componentDidMount() {
        this.setState({ loading: true });
        fetch('https://swapi.co/api/people/1')
            .then(response => response.json())
            .then(data => {
                this.setState(
                    {
                        character: this.state.character.concat(data),
                        loading: false
                    }
                );
                console.log('newstate', this.state.character);
            });
    }
    render() {
        return (
    <div><h3>Name: {this.state.character[0].name}</h3>
            </div>
        )
    }

}

I don't know how to fix this.

It worked with an object because you tried to access a property that doesn't exist on the object and got undefined instead

When you try to access the data before the http request finishes, array[0] is undefined and will throw an error when you try to access a property on undefined

There are a couple of ways you can make it work, when using arrays you can just map over the array and render the elements, if the array is empty nothing will be rendered

<div>
  {this.state.character.map(char => (
    <h3 key={char.name}>Name: {char.name}</h3> // don't forget the key
  )}
</div>

You can also check if there is an element inside the array before trying to access a property on the element if you only want to render the first element

<div>
  {this.state.character[0] && (
    <h3>Name: {this.state.character[0].name}</h3>
  )}
</div>

But, it looks like you are storing a single character inside the array and it will make sense to just keep it as an object, use arrays when you need to store multiple items instead of just one

For updating the state based on the previous state, you should use a function instead of an object:

this.setState(state => (
  {
    character: state.character.concat(data),
    loading: false
  }
), () => {
  console.log(this.state);
});

Note that react state updates may be asynchronous, that's why I added a callback to my example for tracing the new state.

You can read more about React state and lifecycle in the official documentation: https://reactjs.org/docs/state-and-lifecycle.html#using-state-correctly

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM