Ste Royle
Ste Royle

Reputation: 3

Length of array in React isn't matching up to the number of elements it has

Everytime my card component is clicked it is running the cardSelected() function. I can see that the state array selected is being correctly updated with the card ids but when I check the length of the array after using setState() it is one out.

  1. array starts empty
  2. after first card is clicked, the array is updated with with the card id
  3. console.log(this.state.selected.length) straight after still shows the length as 0 when I am expecting it to be 1 and can see it has 1 value in state.

cardSelected = id => {
  this.setState(prevState => ({
    selected: [...prevState.selected, id]
  }));

  console.log(this.state.selected.length);
};

Upvotes: 0

Views: 620

Answers (3)

vijay krishna
vijay krishna

Reputation: 524

As some of the peers answered, setState is asnyc. Not that there's anything wrong with code people suggested. I think you can write your logic better in the below way.

cardSelected = id => {
        const selected = [...this.state.selected, id];
        this.setState({ selected: selected });
    };

And you can better debug your state values using react developer tools chrome extension instead of logging everything. If you still feel like logging to console is better, then you can try logging in render() method or componentDidUpdate() as they are the right places to check your data.

Upvotes: 0

Andre Knob
Andre Knob

Reputation: 831

This happens because setState may be asynchronous, I recommend the reading of this documentation.

On your code, you can use a callback function as a second argument to the setState function, that will be executed when the new state is defined.

cardSelected = id => {
  this.setState(prevState => ({
    selected: [...prevState.selected, id]
  }), () => {
    console.log(this.state.selected.length)
  });
};

Upvotes: 0

Jordan Enev
Jordan Enev

Reputation: 18644

It's because setState is async.

In order to work, fix it as follows with a callback, executed after the state is updated:

this.setState(prevState => ({
  selected: [...prevState.selected, id]
}),
() => console.log(this.state.selected.length))

Upvotes: 2

Related Questions