Caitlin Wen
Caitlin Wen

Reputation: 111

Component doesn't update after setState

I use a dictionary to store the likes of posts in every card.

constructor(props) {
  super(props);
  this.state = {
    like_dict: {}
  };
  this.likeClicked = this.likeClicked.bind(this)
}

I have a like button on every card and the text denotes the number of likes.

<Button transparent onPress={() => {this.likeClicked(poid, 0)}}>
    <Icon name="ios-heart-outline" style={{ color: 'black' }} />
</Button>
<Text>{this.state.like_dict[poid]}</Text>

The likedClicked function looks like this. I set the state of like_dict, but the text above won't rerender.

likeClicked(poid, liked){
  var like_dict_tmp = this.state.like_dict
  if (liked){
    like_dict_tmp[poid] -= 1
  }else{
    like_dict_tmp[poid] += 1
  }
  this.setState({
    like_dict: like_dict_tmp
  })
}

Upvotes: 0

Views: 1290

Answers (2)

Abid Hasan
Abid Hasan

Reputation: 658

You need to copy the state before modifying it. What you are doing is just creating a link to the state in like_dict_tmp (either use what I am doing below, or use concat with an empty array):

var like_dict_tmp = this.state.like_dict.concat([])

likeClicked(poid, liked) {
  var like_dict_tmp = this.state.like_dict.slice()
  if (liked) {
    like_dict_tmp[poid] -= 1
  } else {
    like_dict_tmp[poid] += 1
  }
  this.setState({
    like_dict: like_dict_tmp
  })
}

Also, {} is an object in JS, and is not typically called a dictionary

Upvotes: 0

Roy Wang
Roy Wang

Reputation: 11260

One of the key principles of React is never mutate the state directly.

When you do var like_dict_tmp = this.state.like_dict, like_dict_tmp is referencing the same object in the state so altering like_dict_tmp will mutate the state directly, so the subsequent setState will not update the component.

You can create a shallow copy with var like_dict_tmp = { ...this.state.like_dict } or replace the whole function with:

this.setState((prevState) => ({
  like_dict: {
    ...prevState,
    [poid]: (prevState[poid] || 0) + (liked ? 1 : -1),
  },
}));

Upvotes: 2

Related Questions