set-state-in-render
Validates against setting state during render, which can trigger additional renders and potential infinite render loops.
Rule Details
Calling setState
during render triggers another render before the current one finishes. This creates an infinite loop that crashes your app.
Common Violations
Invalid
// ❌ setState directly in render
function Component({value}) {
const [count, setCount] = useState(0);
setCount(value); // Infinite loop!
return <div>{count}</div>;
}
Valid
// ✅ Derive during render
function Component({items}) {
const sorted = [...items].sort(); // Just calculate it in render
return <ul>{sorted.map(/*...*/)}</ul>;
}
// ✅ Set state in event handler
function Component() {
const [count, setCount] = useState(0);
return (
<button onClick={() => setCount(count + 1)}>
{count}
</button>
);
}
// ✅ Derive from props instead of setting state
function Component({user}) {
const name = user?.name || '';
const email = user?.email || '';
return <div>{name}</div>;
}
Troubleshooting
I need to reset state when props change
Sometimes you want to reset internal state when a prop changes:
// ❌ Wrong approach
function EditForm({itemId}) {
const [formData, setFormData] = useState({});
// This creates infinite renders
if (itemId !== lastItemId) {
setFormData({});
}
return <form>...</form>;
}
Use a key to reset the component:
// ✅ Use key to reset component
function EditForm({itemId, ...props}) {
return <EditFormInner key={itemId} {...props} />;
}
function EditFormInner() {
const [formData, setFormData] = useState({});
// Component resets when key changes
return <form>...</form>;
}