Reducer Initialization

useReducer(reducer, initialArg, init?) takes an optional third argument. Without it the initial state is initialArg itself. With it, React 7,897 computes the initial state once as init(initialArg) and never calls init again on later renders.

An initializer used for both setup and resetJavaScript
function init(initialCount) {
  return { count: initialCount, history: [] };        // runs once, on mount
}
function reducer(state, action) {
  switch (action.type) {
    case 'increment': return { ...state, count: state.count + 1 };
    case 'reset':     return init(action.payload);    // reuse the same shape
    default: throw new Error('Unknown action: ' + action.type);
  }
}
function Counter({ initialCount }) {
  const [state, dispatch] = useReducer(reducer, initialCount, init);
  return <button onClick={() => dispatch({ type: 'reset', payload: initialCount })}>Reset</button>;
}

Two things make this worth the extra argument. The initial state is often derived — parsed from localStorage, built from a prop, computed from a list — and writing useReducer(reducer, init(initialCount)) would run that work on every render only to throw the result away. And extracting the setup into a named function lets the reset action rebuild the starting state without duplicating its shape.

Like the reducer, init must be pure: Strict Mode calls it twice in development and discards one result, so an initializer that writes to localStorage or bumps a counter misbehaves visibly. That double call is the point — it surfaces impurity while you are still writing the code.