Common React mistakes
The bugs every beginner hits, and how to avoid them.
| Mistake | Fix |
|---|---|
Changing state directly: items.push(x) | Make a new value: setItems([...items, x]) |
| Reading state just after setting it | The new value arrives on the next render. Use setCount((c) => c + 1) to build on the old one |
| No key, or the index as key, in a list | Use a stable id from your data |
| An effect with no dependency array that sets state | It loops forever. List what the effect depends on |
| Copying a prop into state | Use the prop directly, or the copy goes stale |
onClick={save()} | Pass a function: onClick={() => save()} |
| Secret keys in front-end code | Everything in the bundle is public. Keep keys on a server |
Why mutation hides changes
React compares the old and new state with ===. After push, the array is the same object, so React thinks nothing changed and may not redraw.
Expected output
true false 2 3
Stale state
React (JSX)
function Counter() {
const [count, setCount] = useState(0);
function addThreeWrong() {
setCount(count + 1);
setCount(count + 1);
setCount(count + 1); // count is still 0 in all three: the result is 1
}
function addThree() {
setCount((c) => c + 1);
setCount((c) => c + 1);
setCount((c) => c + 1); // each update builds on the last: the result is 3
}
return <button onClick={addThree}>{count}</button>;
}