How to fix Cannot update component state during its rendering phase in React
This error occurs when a React component attempts to call setState or dispatch a state update while the component is currently rendering. This disrupts React's rendering cycle and can cause infinite loops or unpredictable behavior.
Quick fix
Fixes Cannot update component state during its rendering phase
// ❌ Bad: setState during render
function MyComponent({ userId }) {
const [user, setUser] = useState(null);
// This runs during render and causes the error
if (userId !== user?.id) {
setUser(null); // Don't do this!
}
return <div>{user?.name}</div>;
}
// ✅ Good: setState in useEffect
function MyComponent({ userId }) {
const [user, setUser] = useState(null);
useEffect(() => {
// State update happens after render
setUser(null);
// Fetch new user data...
}, [userId]); // Only run when userId changes
return <div>{user?.name}</div>;
}- Move state updates to useEffect
- Fix useEffect dependency arrays
- Move updates to event handlers
- Fix parent-child state synchronization
// ❌ Bad: setState during renderfunction MyComponent({ userId }) {const [user, setUser] = useState(null);// This runs during render and causes the errorif (userId !== user?.id) {setUser(null); // Don't do this!}return <div>{user?.name}</div>;}// ✅ Good: setState in useEffectfunction MyComponent({ userId }) {const [user, setUser] = useState(null);useEffect(() => {// State update happens after rendersetUser(null);// Fetch new user data...}, [userId]); // Only run when userId changesreturn <div>{user?.name}</div>;}Cannot update component state during its rendering phase
What this error means
This error is React's way of preventing a common anti-pattern where state updates happen during the render phase. When a component is rendering, React is calculating what the UI should look like based on the current state and props. If you try to update state during this calculation, it creates a circular dependency: the render triggers a state update, which triggers another render, which triggers another state update, and so on. React's rendering process must be a pure function - given the same inputs (state and props), it should always produce the same output (JSX). State updates during render violate this principle because they introduce side effects into the render phase. This can lead to infinite loops, inconsistent UI states, performance degradation, and unpredictable component behavior. The error typically manifests as a warning in development mode before causing more serious issues. React 18 and later versions have become more strict about detecting and warning about these patterns to help developers catch them early.
Typical symptoms
- Warning message in console: "Cannot update a component while rendering a different component"
- Browser freezing or becoming unresponsive due to infinite render loop
- React DevTools showing rapidly increasing render counts
- Component flickering or displaying inconsistent data
- Application performance severely degraded
- Maximum update depth exceeded error following the initial warning
Common causes
- Calling setState directly in the component body outside of event handlers or effects
- Using useEffect or useLayoutEffect without proper dependency arrays, causing state updates on every render
- Defining event handlers inline that immediately invoke state-updating functions during render
- Calling state updater functions inside render methods of class components
- Updating parent component state from child component during child's render phase
- Using useMemo or useCallback incorrectly to trigger state updates
- Conditional logic that updates state based on props or state during render
How to fix "Cannot update component state during its rendering phase"
If you need to update state in response to prop changes or side effects, use the useEffect hook:
// ❌ Bad: setState during render
function MyComponent({ userId }) {
const [user, setUser] = useState(null);
// This runs during render and causes the error
if (userId !== user?.id) {
setUser(null); // Don't do this!
}
return <div>{user?.name}</div>;
}
// ✅ Good: setState in useEffect
function MyComponent({ userId }) {
const [user, setUser] = useState(null);
useEffect(() => {
// State update happens after render
setUser(null);
// Fetch new user data...
}, [userId]); // Only run when userId changes
return <div>{user?.name}</div>;
}For functional components, always perform state updates inside useEffect with proper dependencies specified.
Ensure your useEffect hooks have complete and correct dependency arrays to prevent updates on every render:
// ❌ Bad: Missing dependency array causes infinite loop
function MyComponent() {
const [count, setCount] = useState(0);
useEffect(() => {
setCount(count + 1); // Runs on every render!
}); // No dependency array
return <div>{count}</div>;
}
// ✅ Good: Empty array runs once, or specify dependencies
function MyComponent() {
const [count, setCount] = useState(0);
useEffect(() => {
// This runs once on mount
const timer = setTimeout(() => setCount(1), 1000);
return () => clearTimeout(timer);
}, []); // Empty array = run once
return <div>{count}</div>;
}An empty dependency array means the effect runs once after mount. Include dependencies that the effect actually depends on.
State updates should happen in response to user events, not during render:
// ❌ Bad: Calling updater during render
function SearchBox({ onSearch }) {
const [query, setQuery] = useState('');
// This runs during every render!
setQuery(getDefaultQuery());
return <input value={query} />;
}
// ✅ Good: Initialize with proper default or update in handler
function SearchBox({ onSearch }) {
const [query, setQuery] = useState(() => getDefaultQuery());
const handleChange = (e) => {
setQuery(e.target.value);
onSearch(e.target.value);
};
return <input value={query} onChange={handleChange} />;
}Use lazy initialization for expensive defaults: useState(() => computeDefault()).
When a child component needs to notify a parent, use callbacks instead of direct state updates:
// ❌ Bad: Child updating parent during render
function Parent() {
const [data, setData] = useState(null);
return <Child onDataChange={setData} />;
}
function Child({ onDataChange }) {
const result = calculateSomething();
onDataChange(result); // Called during render!
return <div>{result}</div>;
}
// ✅ Good: Child uses effect or event handler
function Parent() {
const [data, setData] = useState(null);
return <Child onDataChange={setData} />;
}
function Child({ onDataChange }) {
const result = calculateSomething();
useEffect(() => {
onDataChange(result); // Called after render
}, [result, onDataChange]);
return <div>{result}</div>;
}Alternatively, lift the state calculation to the parent component to avoid the synchronization entirely.
Often you don't need to update state at all - you can derive values from existing state:
// ❌ Bad: Updating state based on other state
function TodoList({ todos }) {
const [filteredTodos, setFilteredTodos] = useState([]);
const [filter, setFilter] = useState('all');
// Anti-pattern: updating state during render
if (filter === 'active') {
setFilteredTodos(todos.filter(t => !t.completed));
}
return <div>{filteredTodos.map(...)}</div>;
}
// ✅ Good: Derive state from props/state
function TodoList({ todos }) {
const [filter, setFilter] = useState('all');
// Calculated during render (no state update needed)
const filteredTodos = useMemo(() => {
return todos.filter(t =>
filter === 'all' ||
(filter === 'active' && !t.completed) ||
(filter === 'completed' && t.completed)
);
}, [todos, filter]);
return <div>{filteredTodos.map(...)}</div>;
}If a value can be computed from existing state or props, don't store it in state - compute it during render.
Advanced notes
React 18+ Automatic Batching: React 18 introduced automatic batching for all state updates, including those in promises, setTimeout, and native event handlers. This reduces unnecessary re-renders but doesn't eliminate the render-phase update restriction.
useEffectEvent (Experimental): React 19 introduces useEffectEvent to solve a related problem where synchronous setState calls within effects can trigger cascading renders. This hook allows you to access the latest props/state without including them in the dependency array.
Class Components: In class components, never call setState in the render() method. Use componentDidMount, componentDidUpdate, or event handlers instead. The getDerivedStateFromProps static method is designed for the specific use case of updating state based on prop changes.
StrictMode Detection: React's StrictMode in development intentionally double-invokes render functions to help detect impure rendering logic. If you see this error only in development, check if you have state updates in your render logic.
Performance Impact: Beyond causing errors, state updates during render severely impact performance. Each update triggers a new render cycle, and if done repeatedly, it can freeze the entire application. React's concurrent features in React 18+ make this even more critical as they rely on predictable rendering behavior.
Debugging Strategy: Use React DevTools Profiler to identify which component is causing excessive renders. Look for components with very high render counts or those that render every time their parent renders. Add console.logs with component names to trace the update chain.
Frequently asked questions
- What does "Cannot update component state during its rendering phase" mean?
- This error is React's way of preventing a common anti-pattern where state updates happen during the render phase. When a component is rendering, React is calculating what the UI should look like based on the current state and props. If you try to update state during this calculation, it creates a circular dependency: the render triggers a state update, which triggers another render, which triggers another state update, and so on.
- How do I fix "Cannot update component state during its rendering phase"?
- This error occurs when a React component attempts to call setState or dispatch a state update while the component is currently rendering. This disrupts React's rendering cycle and can cause infinite loops or unpredictable behavior.
- What causes "Cannot update component state during its rendering phase"?
- Calling setState directly in the component body outside of event handlers or effects Using useEffect or useLayoutEffect without proper dependency arrays, causing state updates on every render Defining event handlers inline that immediately invoke state-updating functions during render
- Is the "Cannot update component state during its rendering phase" error serious?
- Yes. This is a high-severity error that usually blocks work until it is fixed, but the steps above resolve it.