reduxjs/redux · error · Error
Expected the nextReducer to be a function. Instead, received
Error message
Expected the nextReducer to be a function. Instead, received: '${kindOf(nextReducer)}' What it means
replaceReducer(nextReducer) swaps the active reducer, used for hot-reloading and code-splitting. The new value must be a function so dispatch can call it as (state, action) => state. Passing anything else (undefined, object, partial combineReducers result) would break the dispatch loop, so Redux type-checks up front.
Source
Thrown at src/createStore.ts:322
const listeners = (currentListeners = nextListeners)
listeners.forEach(listener => {
listener()
})
return action
}
/**
* Replaces the reducer currently used by the store to calculate the state.
*
* You might need this if your app implements code splitting and you want to
* load some of the reducers dynamically. You might also need this if you
* implement a hot reloading mechanism for Redux.
*
* @param nextReducer The reducer for the store to use instead.
*/
function replaceReducer(nextReducer: Reducer<S, A>): void {
if (typeof nextReducer !== 'function') {
throw new Error(
`Expected the nextReducer to be a function. Instead, received: '${kindOf(
nextReducer
)}'`
)
}
currentReducer = nextReducer as unknown as Reducer<S, A, PreloadedState>
// This action has a similar effect to ActionTypes.INIT.
// Any reducers that existed in both the new and old rootReducer
// will receive the previous state. This effectively populates
// the new state tree with any relevant data from the old one.
dispatch({ type: ActionTypes.REPLACE } as A)
}
/**
* Interoperability point for observable/reactive libraries.
* @returns A minimal observable of state changes.View on GitHub (pinned to 3084fc33bb)
Solutions
- Log `typeof nextReducer` before replaceReducer and confirm it is 'function'.
- When re-splitting, rebuild the combined reducer: `store.replaceReducer(combineReducers({ ...newSlices }))`.
- In HMR, account for default-vs-namespace exports: `require('./reducers').default` for default, `.rootReducer` for named.
- Resolve circular imports before hot-reloading.
Example fix
// before
if (module.hot) {
module.hot.accept('./reducers', () => {
store.replaceReducer(require('./reducers')) // module object, not the reducer fn
})
}
// after
if (module.hot) {
module.hot.accept('./reducers', () => {
const nextRootReducer = require('./reducers').default
store.replaceReducer(nextRootReducer)
})
} Defensive patterns
Strategy: type-guard
Validate before calling
if (typeof nextReducer !== 'function') {
throw new TypeError(`nextReducer must be a function, got ${typeof nextReducer}`)
}
store.replaceReducer(nextReducer) Type guard
const isReducer = (x): x is (s:any, a:any)=>any => typeof x === 'function'
Prevention
- In HMR, account for default-vs-namespace exports when re-requiring reducers.
- Rebuild combineReducers when injecting new slices dynamically.
- Log typeof nextReducer before replaceReducer.
- Avoid circular imports between reducers and the store module.
When it happens
Trigger: store.replaceReducer(undefined) — a new reducer import resolved to undefined; replaceReducer called with a slice map instead of combineReducers(map); replaceReducer(combineReducers) passing the function reference instead of calling it; circular import making the new reducer undefined at hot-reload time.
Common situations: Webpack HMR `module.hot.accept('./reducers', () => store.replaceReducer(require('./reducers').default))` where the default export is missing; code-splitting that injects a slice object instead of a recombined root reducer; refactor that renamed the reducer export.
Related errors
- Expected the root reducer to be a function. Instead, receive
- bindActionCreators expected an object or a function, but ins
- It looks like you are passing several store enhancers to cre
- Expected the enhancer to be a function. Instead, received: '
- You may not call store.getState() while the reducer is execu
AI-assisted analysis of reduxjs/redux@3084fc33bb (2026-08-12).
Data as JSON: /api/errors/ceb87a6a89e880a4.
Report an issue: GitHub.