How to fix useReducer received an invalid initializer in React
This error occurs when passing an invalid third argument to useReducer. The initializer must be a function reference that returns initial state, not the result of calling a function or an incorrect type.
Quick fix
Fixes useReducer received an invalid initializer
// Don't call the function with ()
const [state, dispatch] = useReducer(reducer, initialArg, initFunction());- Verify you are passing a function reference, not a function call
- Ensure the initializer function returns the initial state
- Check that the third argument is actually a function
- Verify the initializer is a synchronous function
// Don't call the function with ()const [state, dispatch] = useReducer(reducer, initialArg, initFunction());useReducer received an invalid initializer
What this error means
The "useReducer invalid initializer" error indicates that the optional third argument passed to React's useReducer hook is not a valid initializer function. The useReducer hook accepts three arguments: the reducer function, the initial state (or initial argument), and an optional initializer function for lazy initialization. When you provide a third argument, React expects it to be a pure function that takes the second argument (initialArg) as input and returns the initial state. This initializer function runs only once during the first render, allowing you to defer expensive computations or perform conditional initialization logic. The error occurs when you pass something other than a function reference as the third argument, or when you accidentally pass the result of calling a function instead of the function itself. This is a runtime error that prevents the component from mounting correctly.
Typical symptoms
- Component fails to mount with a runtime error about invalid initializer
- Console shows error mentioning useReducer received an invalid initializer argument
- TypeScript reports type errors about the third argument to useReducer
- Initial state is not being set correctly when using lazy initialization
- Error occurs immediately when component tries to render for the first time
- Development mode shows warnings about invalid hook arguments
Common causes
- Passing the result of calling an initializer function instead of the function reference itself
- Providing a non-function value as the third argument to useReducer
- Accidentally passing undefined or null as the third argument when attempting lazy initialization
- Using TypeScript with incorrect type annotations for the initializer parameter
- Passing an arrow function that does not return a value
- Attempting to pass an async function as the initializer (must be synchronous)
- Incorrectly destructuring or spreading the initializer function
- Mixing up argument order and passing the initializer in the wrong position
How to fix "useReducer received an invalid initializer"
The most common mistake is calling the initializer function instead of passing the function itself. Check your useReducer call:
Incorrect:
// Don't call the function with ()
const [state, dispatch] = useReducer(reducer, initialArg, initFunction());Correct:
// Pass the function reference without calling it
const [state, dispatch] = useReducer(reducer, initialArg, initFunction);The initializer should be a function reference that React will call internally with the initialArg parameter.
Your initializer function must return a value that will be used as the initial state. Verify your function has a return statement:
// Correct initializer function
function init(initialArg) {
return {
count: initialArg,
timestamp: Date.now()
};
}
const [state, dispatch] = useReducer(reducer, 0, init);The function receives the second argument (initialArg) as its parameter and must return the complete initial state object.
If you're conditionally using an initializer, make sure you're not passing undefined or other non-function values:
Incorrect:
const initializer = someCondition ? initFunction : undefined;
const [state, dispatch] = useReducer(reducer, initialArg, initializer);Correct - omit third argument entirely if not needed:
const [state, dispatch] = someCondition
? useReducer(reducer, initialArg, initFunction)
: useReducer(reducer, initialArg);Only pass the third argument when you have a valid function to provide.
The initializer function must be synchronous and cannot be an async function. React calls this function during render and expects an immediate return value:
Incorrect:
// Async functions are not valid initializers
async function initAsync(initialArg) {
const data = await fetchData();
return { data };
}
const [state, dispatch] = useReducer(reducer, null, initAsync);Correct:
// Use synchronous initialization, handle async operations in useEffect
function init(initialArg) {
return { data: null, loading: true };
}
const [state, dispatch] = useReducer(reducer, null, init);
useEffect(() => {
fetchData().then(data => dispatch({ type: 'SET_DATA', payload: data }));
}, []);When using TypeScript, ensure your initializer function has the correct type signature:
type State = { count: number };
type Action = { type: 'increment' } | { type: 'decrement' };
function reducer(state: State, action: Action): State {
switch (action.type) {
case 'increment':
return { count: state.count + 1 };
case 'decrement':
return { count: state.count - 1 };
default:
return state;
}
}
// Properly typed initializer function
function init(initialCount: number): State {
return { count: initialCount };
}
const [state, dispatch] = useReducer(reducer, 0, init);The initializer should accept the same type as your initialArg and return the state type.
If you don't need lazy initialization, you can simplify by using only two arguments:
Simple initialization (no third argument):
const initialState = { count: 0, timestamp: Date.now() };
const [state, dispatch] = useReducer(reducer, initialState);Lazy initialization (with third argument):
function init(initialCount) {
return { count: initialCount, timestamp: Date.now() };
}
const [state, dispatch] = useReducer(reducer, 0, init);Lazy initialization is beneficial when the initial state calculation is expensive or when you need to derive initial state from props. Otherwise, direct initialization is simpler and less error-prone.
Advanced notes
When to use lazy initialization: Lazy initialization with the third argument is most useful when creating the initial state requires expensive computations (like parsing large JSON, complex calculations, or reading from localStorage), when you want to avoid recreating the initial state object on every render during development with Strict Mode, or when you need to compute initial state based on props or arguments.
Pure function requirement: The initializer function must be a pure function - it should always return the same result given the same input, have no side effects, and not rely on external state. React may call this function multiple times in development mode to help detect impurities.
TypeScript edge case: There's a known TypeScript type inference issue (GitHub issue #27052) where TypeScript may incorrectly require the third argument even when it's optional. If you encounter this, you can explicitly type your useReducer call or update your TypeScript and React type definitions to the latest versions.
Comparison with useState: While useState also supports lazy initialization with a function argument, useReducer's lazy initialization pattern is different - useState takes the function as the first argument, while useReducer takes it as the third argument with the initial value as the second argument passed to that function.
Frequently asked questions
- What does "useReducer received an invalid initializer" mean?
- The "useReducer invalid initializer" error indicates that the optional third argument passed to React's useReducer hook is not a valid initializer function. The useReducer hook accepts three arguments: the reducer function, the initial state (or initial argument), and an optional initializer function for lazy initialization. When you provide a third argument, React expects it to be a pure function that takes the second argument (initialArg) as input and returns the initial state.
- How do I fix "useReducer received an invalid initializer"?
- This error occurs when passing an invalid third argument to useReducer. The initializer must be a function reference that returns initial state, not the result of calling a function or an incorrect type.
- What causes "useReducer received an invalid initializer"?
- Passing the result of calling an initializer function instead of the function reference itself Providing a non-function value as the third argument to useReducer Accidentally passing undefined or null as the third argument when attempting lazy initialization
- Is the "useReducer received an invalid initializer" error serious?
- It is a medium-severity error โ more of a blocker than a risk. The steps above resolve it.
Official resources & further reading
- ๐React Official Documentation
- ๐React: useReducer Reference Documentation(Official Docs)
- ๐ฌGitHub: useReducer initializer TypeScript type issue(Stack Overflow)
- ๐ฌGitHub: useState style lazy initialization in useReducer(Stack Overflow)