When using React’s setState()
with a function argument but not actually utilizing the previous state, you’re potentially introducing unnecessary complexity and minor performance overhead. Here’s what you need to know:
The Anti-Pattern
// ❌ Unnecessary function form
this.setState(() => ({
count: 42
}));
Why This is Problematic
- Unnecessary Function Invocation: React has to call your function just to get the new state
- Reduced Readability: Makes code harder to understand at a glance
- Potential Confusion: Other developers might expect you to use prevState
- Micro-Performance Impact: Extra function call has a tiny cost
Correct Approaches
1. Simple Object Form (Recommended)
// ✅ Preferred when not using prevState
this.setState({ count: 42 });
2. When You Actually Need Functional Updates
Only use the function form when you need previous state:
// ✅ Correct usage of functional form
this.setState(prevState => ({
count: prevState.count + 1
}));
Function Component Equivalent
The same principles apply to useState
hooks:
const [count, setCount] = useState(0);
// ❌ Unnecessary function
setCount(() => 42);
// ✅ Better
setCount(42);
// ✅ Only use function when needed
setCount(prev => prev + 1);
When Function Form is Acceptable Without prevState
There are rare cases where you might intentionally use the function form without prevState:
- Ensuring Fresh State in async scenarios (though there are better patterns)
- Consistent Coding Style if your team prefers it
- Future-Proofing if you might need prevState later
Performance Considerations
While the performance difference is negligible in most cases, the object form is technically:
- Faster to Execute: No extra function call
- Easier to Optimize: For React’s internals
- More Predictable: For React’s batching mechanism
Best Practice Recommendation
Always use the simplest form that meets your needs:
- Object form for simple updates
- Function form when you need previous state or sequential updates
- Avoid function form when it provides no benefit