Fix: React Cannot update a component while rendering a different component
Quick Answer
How to fix React Cannot update a component while rendering a different component caused by setState during render, context updates in render, and Redux dispatch in render.
The Error
Your React app logs this warning (React 18+) or throws an error:
Warning: Cannot update a component (`ParentComponent`) while rendering a different component (`ChildComponent`).
To locate the bad setState() call inside `ChildComponent`, follow the component stack trace.Or variations:
Warning: Cannot update a component from inside the function body of a different component.Warning: Cannot update during an existing state transition (such as within `render`).
Render methods should be a pure function of props and state.You called setState, dispatched a Redux action, or updated a context value during the render phase of another component. React’s render phase must be pure — no side effects.
Why This Happens
React renders components by calling their function body (or render() method in class components). During this render phase, React expects the function to be pure: it should only compute the output based on props and state, with no side effects.
When you call setState (or any state update) during the render of a different component, React detects this violation and warns you. This happens because:
- Setting state during render triggers another render, which can cause infinite loops.
- React cannot guarantee consistent rendering if components update each other’s state during rendering.
- The render phase should be predictable — the same props and state should always produce the same output.
Common causes:
- Calling a callback prop that sets parent state during render.
- Dispatching Redux actions during render.
- Updating context values during render.
- Calling
setStatedirectly in the function body (not insideuseEffector an event handler). - Using
useSyncExternalStoreor subscribing to external stores incorrectly.
Fix 1: Move State Updates to useEffect
The most common fix. State updates based on props or other state should happen in useEffect:
Broken — setState during render:
function ChildComponent({ items, onCountChange }) {
const count = items.length;
onCountChange(count); // Calls parent's setState during render!
return <div>{count} items</div>;
}
function ParentComponent() {
const [count, setCount] = useState(0);
const items = useItems();
return <ChildComponent items={items} onCountChange={setCount} />;
}Fixed — use useEffect:
function ChildComponent({ items, onCountChange }) {
const count = items.length;
useEffect(() => {
onCountChange(count); // Runs after render, not during
}, [count, onCountChange]);
return <div>{count} items</div>;
}Fixed — derive the value instead of syncing state:
function ParentComponent() {
const items = useItems();
const count = items.length; // Derive directly — no state sync needed!
return (
<>
<div>Total: {count}</div>
<ItemList items={items} />
</>
);
}Pro Tip: Before adding
useEffectto sync state, ask: “Can I derive this value from existing state or props?” Derived values do not need their own state. This eliminates the entire category of “update during render” bugs and reduces unnecessary re-renders.
Fix 2: Fix Callbacks That Set State
A common pattern is passing a callback prop that gets called during render:
Broken — onLoad callback during render:
function DataLoader({ url, onLoad }) {
const data = useFetchedData(url);
if (data) {
onLoad(data); // Called during render!
}
return <div>{data ? "Loaded" : "Loading..."}</div>;
}
function App() {
const [data, setData] = useState(null);
return <DataLoader url="/api/data" onLoad={setData} />;
}Fixed — use useEffect for the callback:
function DataLoader({ url, onLoad }) {
const data = useFetchedData(url);
useEffect(() => {
if (data) {
onLoad(data);
}
}, [data, onLoad]);
return <div>{data ? "Loaded" : "Loading..."}</div>;
}Fixed — lift state up instead of syncing:
function App() {
const data = useFetchedData("/api/data");
return (
<div>
{data ? <DataDisplay data={data} /> : <Loading />}
</div>
);
}Fix 3: Fix Redux Dispatch During Render
Dispatching Redux actions during render causes the same issue:
Broken:
function UserProfile({ userId }) {
const dispatch = useDispatch();
const user = useSelector(state => state.users[userId]);
if (!user) {
dispatch(fetchUser(userId)); // Dispatch during render!
}
return user ? <div>{user.name}</div> : <div>Loading...</div>;
}Fixed — dispatch in useEffect:
function UserProfile({ userId }) {
const dispatch = useDispatch();
const user = useSelector(state => state.users[userId]);
useEffect(() => {
if (!user) {
dispatch(fetchUser(userId));
}
}, [userId, user, dispatch]);
return user ? <div>{user.name}</div> : <div>Loading...</div>;
}Fixed — with RTK Query (automatic fetching):
function UserProfile({ userId }) {
const { data: user, isLoading } = useGetUserQuery(userId);
if (isLoading) return <div>Loading...</div>;
return <div>{user.name}</div>;
}Fix 4: Fix Context Updates During Render
Updating context value during render:
Broken:
function ThemeDetector({ children }) {
const { setTheme } = useContext(ThemeContext);
const prefersDark = useMediaQuery('(prefers-color-scheme: dark)');
setTheme(prefersDark ? 'dark' : 'light'); // Updates context during render!
return children;
}Fixed:
function ThemeDetector({ children }) {
const { setTheme } = useContext(ThemeContext);
const prefersDark = useMediaQuery('(prefers-color-scheme: dark)');
useEffect(() => {
setTheme(prefersDark ? 'dark' : 'light');
}, [prefersDark, setTheme]);
return children;
}Fix 5: Fix Conditional State Initialization
Setting state based on a condition during render:
Broken:
function SearchResults({ query, results }) {
const [selectedId, setSelectedId] = useState(null);
// Resets selection when results change — BUT does it during render!
if (results.length > 0 && selectedId === null) {
setSelectedId(results[0].id);
}
return <ResultsList results={results} selectedId={selectedId} />;
}Fixed — use useEffect:
function SearchResults({ query, results }) {
const [selectedId, setSelectedId] = useState(null);
useEffect(() => {
if (results.length > 0) {
setSelectedId(results[0].id);
}
}, [results]);
return <ResultsList results={results} selectedId={selectedId} />;
}Fixed — use a key to reset state (React pattern):
function App() {
const [query, setQuery] = useState("");
const results = useSearch(query);
// key={query} unmounts/remounts SearchResults, resetting its state
return <SearchResults key={query} results={results} />;
}
function SearchResults({ results }) {
// State is fresh on every new query because the component remounts
const [selectedId, setSelectedId] = useState(
results.length > 0 ? results[0].id : null
);
return <ResultsList results={results} selectedId={selectedId} />;
}Common Mistake: Using
useEffectto “sync” state that could be derived or using it to reset state when props change. Consider using thekeyprop to reset component state, or derive the value directly from props without state.
Fix 6: Fix Custom Hooks That Set State
Custom hooks that set state during execution:
Broken:
function useFormValidation(values, setErrors) {
const errors = validate(values);
if (Object.keys(errors).length > 0) {
setErrors(errors); // Sets parent state during render!
}
return errors;
}Fixed — return the errors, let the caller handle them:
function useFormValidation(values) {
return useMemo(() => validate(values), [values]);
}
function MyForm() {
const [values, setValues] = useState({});
const errors = useFormValidation(values);
// errors is derived, no state sync needed
}Fix 7: Fix Class Component render() Side Effects
In class components, side effects in render() cause the same issue:
Broken:
class Dashboard extends React.Component {
render() {
if (this.props.data.length > this.state.lastCount) {
this.props.onDataChange(this.props.data.length); // Side effect in render!
}
return <div>{this.props.data.length} items</div>;
}
}Fixed — use componentDidUpdate:
class Dashboard extends React.Component {
componentDidUpdate(prevProps) {
if (this.props.data.length !== prevProps.data.length) {
this.props.onDataChange(this.props.data.length);
}
}
render() {
return <div>{this.props.data.length} items</div>;
}
}Fix 8: Use useDeferredValue or startTransition
For state updates that should not block rendering:
import { useDeferredValue, startTransition } from 'react';
function SearchPage() {
const [query, setQuery] = useState('');
const deferredQuery = useDeferredValue(query);
return (
<>
<input value={query} onChange={e => setQuery(e.target.value)} />
<Results query={deferredQuery} />
</>
);
}Using startTransition for non-urgent updates:
function handleClick() {
startTransition(() => {
setExpensiveState(computeNewState());
});
}Still Not Working?
Use React Strict Mode to catch these issues early. Strict Mode intentionally double-renders components to expose side effects:
<React.StrictMode>
<App />
</React.StrictMode>Check for third-party libraries that set state during render. Some older libraries are not compatible with React 18’s stricter rendering model.
Check for useSyncExternalStore issues. If you subscribe to an external store, ensure the getSnapshot function returns a consistent value during rendering.
For infinite re-render loops, see Fix: React useEffect infinite loop. For rendering object errors, see Fix: Objects are not valid as a React child. For missing dependency warnings, see Fix: React useEffect missing dependency.
Solo developer based in Japan. Every solution is cross-referenced with official documentation and tested before publishing.
Was this article helpful?
Related Articles
Fix: React Warning: Failed prop type
How to fix the React 'Warning: Failed prop type' error. Covers wrong prop types, missing required props, children type issues, shape and oneOf PropTypes, migrating to TypeScript, default props, and third-party component mismatches.
Fix: React TypeError: Cannot read property 'map' of undefined
How to fix React TypeError Cannot read property map of undefined caused by uninitialized state, async data loading, wrong API response structure, and missing default values.
Fix: Invalid hook call. Hooks can only be called inside of the body of a function component
How to fix the React Invalid hook call error caused by mismatched React versions, duplicate React copies, calling hooks outside components, and class component usage.
Fix: Objects are not valid as a React child (found: [object Object])
How to fix the React error 'Objects are not valid as a React child' caused by rendering plain objects, Date objects, Promises, or API responses directly in JSX.