Welcome to the Treehouse Community
Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.
Looking to learn something new?
Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.
Start your free trialjobbol
Full Stack JavaScript Techdegree Student 17,877 PointsSet state function updates twice
I noticed handleScoreChange could be simplified by changing the code from:
const [players, setPlayers] = React.useState(/**/);
const handleScoreChange = (id, delta) => {
setPlayers(prevPlayers => prevPlayers.map(player => {
if (player.id === id) { //changing this if statement
return {
name: player.name,
score: player.score + delta,
id: player.id
}
}
return player;
}));
}
To:
if (player.id === id) { //To this
player.score += delta;
}
return player;
}));
}
However, React runs this twice. Clicking the increment button causes the score to be two instead of one.
I tested this outside of React with vanilla JS here and saw no issue: https://jsbin.com/tocaxufipe/edit?js,console
Why does React do this differently?
1 Answer
Travis Alstrand
Data Analysis Techdegree Graduate 49,443 PointsThe behavior you're observing is related to the immutability of state in React. React uses a shallow comparison when determining whether to re-render components or not. When you mutate the state directly (as in your simplified if
statement), React might not be able to correctly detect changes and could lead to unexpected behavior.
In your original code, you're creating a new player object when you need to update the score. This guarantees a new reference in memory, allowing React to easily detect changes using a shallow comparison.
return {
name: player.name,
score: player.score + delta,
id: player.id
}
In the modified version, you're directly modifying the score property on the existing player object:
player.score += delta;
This means the reference to the player object hasn't changed, so React may not realize that a change has been made. As a result, it can lead to unexpected re-renders or missed updates.
The original approach adheres to the best practice of not mutating state directly in React. Always ensure you return a new object or array when updating the state, as this ensures React can correctly and efficiently detect changes and re-render components as needed.
jobbol
Full Stack JavaScript Techdegree Student 17,877 PointsThat makes so much sense with the new Object creating a new memory reference, because I had also tried:
return {...player, score: player.score + delta};
And this ended up working.
Thanks again. I will remember to create new objects and arrays.
Travis Alstrand
Data Analysis Techdegree Graduate 49,443 PointsTravis Alstrand
Data Analysis Techdegree Graduate 49,443 PointsAwesome!! You're very welcome