Reputation: 111
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
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
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