can someone tell me why is this “upvote” onClick handler firing twice? the logs would indicate it’s only running once but the score it controls increases by 2
export default class Container extends Component {
constructor(props) {
super(props);
this.state = {
jokes: [],
};
this.getNewJokes = this.getNewJokes.bind(this);
this.retrieveJokes = this.retrieveJokes.bind(this);
this.upVote = this.upVote.bind(this);
}
upVote(id) {
this.setState(state => {
//find the joke with the matching id and increase score by one
const modifiedJokes = state.jokes.map(joke => {
if (joke.id === id) {
joke.score = joke.score + 1;
}
return joke;
});
console.log(modifiedJokes);
return { jokes: modifiedJokes };
});
}
render() {
return (
<div>
<h1>Container</h1>
{this.state.jokes.map(joke => (
<Joke
key={joke.id}
id={joke.id}
joke={joke.joke}
score={joke.score}
upVote={this.upVote}
downVote={this.downVote}
/>
))}
</div>
);
}
}
on the other hand if I rewrite the handler this way, then it fires only once
upVote(id) {
const modifiedJokes = this.state.jokes.map(joke => {
if (joke.id === id) {
joke.score = joke.score + 1;
}
return joke;
});
this.setState({ jokes: modifiedJokes });
};
Advertisement
Answer
My best guess is that in the first case, you are also modifying the state directly, when you do joke.score = joke.score + 1;
Because you are doing this mapping directly on state array variable, and in Javascript, when using array, you are only working with pointer to that array, not creating a copy of that array.
So the mapping function probably takes a shallow copy of the array, and there’s where problem happens.
You can use lodash to create a deep copy of the state array before you going to work with it, which will not cause your problem: