Mistakes Every React Developer Makes Exactly Once
State Pitfalls
The handful of state mistakes that bite everyone — collected so you can recognize them in the wild.
What you'll learn
- Spot common state bugs in your own code
- Know the right fix for each
A grab-bag of the most common state mistakes. None of them are deep — just easy to make and easy to fix once you’ve seen the pattern.
1. Reading State Right After Setting It
// ✗
setCount(count + 1);
console.log(count); // OLD value State updates queue a re-render. count in this render is fixed.
If you need the new value in this turn, compute it locally:
const next = count + 1;
setCount(next);
console.log(next); 2. Storing Derived Values
// ✗ Two state slots, easy to drift
const [items, setItems] = useState([]);
const [count, setCount] = useState(0);
// ✓ Derive
const count = items.length; 3. Mutating Instead of Replacing
// ✗
items.push(newItem);
setItems(items);
// ✓
setItems([...items, newItem]); 4. Using Index as a Key in a Reorderable List
// ✗ Looks fine until you reorder
{items.map((item, i) => <Row key={i} item={item} />)}
// ✓
{items.map(item => <Row key={item.id} item={item} />)} 5. Setting State in the Render Body
// ✗ Infinite loop — every render queues another render
function Bad() {
const [n, setN] = useState(0);
setN(n + 1);
return <p>{n}</p>;
} State updates belong in event handlers, effects, or other reactions to something happening — never in the render body directly. (There’s a narrow exception with stale state synchronization, but treat it as “never” for now.)
6. The Falsy 0 in &&
// ✗ Renders the literal "0" when count is 0
{count && <Badge>{count}</Badge>}
// ✓
{count > 0 && <Badge>{count}</Badge>} 7. Updater Form For Dependent Updates
// ✗ Three setters, same snapshot → final value is +1
setCount(count + 1);
setCount(count + 1);
setCount(count + 1);
// ✓ Updater form stacks correctly → +3
setCount(prev => prev + 1);
setCount(prev => prev + 1);
setCount(prev => prev + 1); 8. Object Identity Is What Matters
// Re-renders, even though the contents look the same
setUser({ ...user }); React compares references. A new object is a new reference, even if every field is identical.
Up Next
Time for the second-most-used hook: side effects.
useEffect →