Skip to content
masterclassBuddyTech Buzz5 fresh blogs · 5:00 AM IST

Redux Toolkit · Function

createReducer

createReducer constructs a Redux reducer from initial state and a builder callback. It supports exact action cases, matchers, default handling, and Immer-powered immutable updates written with mutating syntax.

How it works

createReducer builds a reducer from an initial state and a builder callback. The callback registers exact action handlers, predicate-based matchers, and an optional fallback; Immer lets case reducers express updates with mutating syntax while producing immutable results.

Syntax

createReducer<State>(initialState, (builder) => { builder.addCase(actionTypeOrCreator, caseReducer); builder.addMatcher(matcher, caseReducer); builder.addDefaultCase(caseReducer); })

Parameters

NameTypeDescription
initialStateState | (() => State)The starting state value, or a lazy initializer function that returns it when called.
builderCallback(builder) => voidA builder callback that registers case reducers, matchers, and an optional default case.

Returns

A Redux reducer function with an attached getInitialState method.

Key points

  • The second argument is a builder callback used to configure the reducer.
  • The builder exposes three registration methods: addCase, addMatcher, and addDefaultCase.
  • The initial state may be supplied lazily through a function.
  • Matching handlers run sequentially in the order they were registered.
  • The returned reducer includes getInitialState for obtaining its initial state.

Common mistakes

  • An exact action-type case runs before any matching predicates.
  • An unmatched action preserves the existing state rather than invoking an implicit update.

Example: Typed createReducer with addCase

import { createAction, createReducer } from '@reduxjs/toolkit'

type CounterState = number
const increment = createAction<number>('counter/increment')

const counterReducer = createReducer<CounterState>(0, (builder) => {
  builder.addCase(increment, (state, action) => state + action.payload)
})

console.log(counterReducer(0, increment(3))) // 3

Defines a reducer with an initial numeric state and a typed action handler.

When to use it

Builder-based action routing

A reducer must handle several action types without a switch statement.

Immer-backed updates

A reducer needs concise immutable updates for nested objects or arrays.

Matcher-driven handling

Several related actions share a predicate-based response.

Lazy initial state

State requires setup only when the reducer first initializes.

Interview questions

QWhat does createReducer accept and how are handlers registered?

createReducer accepts an initial state, which can be a value or a lazy initializer, and a builder callback. The builder registers handlers with addCase, addMatcher, or addDefaultCase.

Follow-up: How are multiple matches processed? An exact case runs first, then every matching matcher in declaration order; a default runs only if none ran.

QWhy can a createReducer case reducer use mutating syntax?

Immer supplies a proxy draft to case reducers, so code can appear to mutate state while Immer converts those operations into immutable updates. This applies to case reducers passed to createReducer.

Follow-up: What happens when a reducer returns a value? The returned value becomes the next state, while draft mutations are another supported update style.

QWhat does createReducer return?

The generated reducer can be passed to Redux as a normal reducer and has a getInitialState function attached. That method returns the reducer's initial state when called.

Follow-up: Why might the initial state be a function? A lazy initializer defers creation until the reducer needs the initial state.

  • createAction
  • createSlice
  • addCase
  • addMatcher
  • addDefaultCase
  • isAnyOf
  • isAllOf

Source: createReducer | Redux. Checked 2026-10-15.