The Problem
React enforces a strict rule: state updates must happen during event handlers or effects, never during the render phase itself. When you break this rule, React throws a hard error in development mode.
Symptoms
- Red error screen: "Cannot update a component while rendering a different component"
- The error names both the calling component and the target component
- App works in some flows but crashes on specific user interactions
- Error only appears in React 18+ with Strict Mode enabled
The Root Cause
This error occurs when one component triggers a state update in another component (or itself) during the render phase. Common triggers include:
- 1.Calling
setStatedirectly in the component body (not inside an effect or handler) - 2.A parent passing a callback that mutates child state, and the child calls it during render
- 3.Context consumers updating context values during render
Real Error Message
Error: Cannot update a component (`App`) while rendering a different
component (`Child`). To locate the bad setState() call inside `Child`,
follow the stack trace as described in the React docs.
at Child
at div
at AppReal-World Scenario
```javascript // BAD: State update during render function Child({ onValueChange }) { const [value, setValue] = useState('');
// This runs during render! It calls parent's setState during child's render. onValueChange(value);
return <input value={value} onChange={e => setValue(e.target.value)} />; }
function App() { const [childValue, setChildValue] = useState(''); return <Child onValueChange={setChildValue} />; } ```
How to Fix It
Fix 1: Move the Update to useEffect
```javascript function Child({ onValueChange }) { const [value, setValue] = useState('');
useEffect(() => { onValueChange(value); }, [value, onValueChange]);
return <input value={value} onChange={e => setValue(e.target.value)} />; } ```
Now the parent state update happens inside an effect, after render completes.
Fix 2: Use a Ref for Deferred Updates
```javascript function Child({ onValueChange }) { const [value, setValue] = useState(''); const pendingRef = useRef(value);
useEffect(() => { if (pendingRef.current !== value) { onValueChange(value); pendingRef.current = value; } }, [value, onValueChange]);
return <input value={value} onChange={e => setValue(e.target.value)} />; } ```
Fix 3: Lift State Up Properly
// Better architecture: parent owns the state
function App() {
const [value, setValue] = useState('');
return <input value={value} onChange={e => setValue(e.target.value)} />;
}If the parent needs the value, it should own the state directly rather than having the child push it up during render.
Prevention
- Never call setState in the component body outside of event handlers
- Use the
react-hooks/exhaustive-depsESLint rule - Enable React Strict Mode in development to catch these errors early
- Keep state ownership clear: the component that needs the value should own it