This error occurs when you attempt to modify React state directly within a useReducer hook without dispatching an action. It breaks the fundamental Redux pattern where state updates must be triggered by dispatched actions. This guide explains how to identify and fix this common mistake.
The error message indicates that you're trying to update the state managed by useReducer synchronously, bypassing the dispatch function. In Redux and React's useReducer, state updates must be pure and predictable, achieved only by dispatching action objects. Direct mutations lead to inconsistent UI and debugging difficulties because React cannot track changes and schedule proper re-renders.
Examine your component code and look for any lines where you're modifying the state variable directly. Common patterns include:
- state.push(newItem)
- state.property = newValue
- state = newState (reassignment)
Check both the component body and any helper functions that receive state as an argument. Use your browser's developer tools to set breakpoints or add console logs to trace the origin of the mutation.
Instead of modifying state directly, create an action object and call dispatch. For example:
// ❌ Wrong
directUpdate = () => {
state.count = state.count + 1;
};
// ✅ Correct
const increment = () => {
dispatch({ type: 'INCREMENT' });
};Ensure your reducer handles the action type appropriately, returning a new state object rather than mutating the existing one.
Verify that your reducer function includes a case for the dispatched action type and returns a new state object immutably. Example:
function reducer(state, action) {
switch (action.type) {
case 'INCREMENT':
return { ...state, count: state.count + 1 };
default:
return state;
}
}Avoid side effects inside the reducer. If you need asynchronous operations, use middleware like Redux Thunk or move logic to action creators.
After making changes, run your application and verify that the error no longer appears. Test the state updates by interacting with your UI and confirming that the state changes as expected. Use React DevTools and Redux DevTools to inspect state changes and action history. Write unit tests for your reducer to ensure it handles actions correctly and immutably.
This error often arises when migrating from useState to useReducer or when integrating Redux patterns. Remember that useReducer expects immutable updates; always return a new state object. For complex state shapes, consider using Immer or Redux Toolkit to simplify immutable logic. Additionally, be mindful of stale closures when dispatching actions inside useEffect dependencies; include dispatch in the dependency array if needed.
React Hook useCallback has a missing dependency: 'variable'. Either include it or remove the dependency array react-hooks/exhaustive-deps
React Hook useCallback has a missing dependency
Cannot use private fields in class components without TS support
Cannot use private fields in class components without TS support
Cannot destructure property 'xxx' of 'undefined'
Cannot destructure property of undefined when accessing props
useNavigate() may be used only in the context of a <Router> component.
useNavigate() may be used only in the context of a Router component
Cannot find module or its corresponding type declarations
How to fix "Cannot find module or type declarations" in Vite