# Use Redux-style actions

Handle store updates through a reducer and dispatched actions when a reducer-based action pattern fits your application.

Use this pattern when you want one reducer to describe how explicit action objects change a store. Zustand does not require reducers or dispatched actions; its recommended pattern is to keep actions with state and update through `set` or `setState`.

## Create a reducer-backed store

The [`redux`](https://bench-zustand-6l.atloria.app/p/bench-zustand-6l-TzFgfybqJX/developer/zustand-middleware#redux) middleware takes a reducer and initial state, then returns a state creator with `dispatch`. Wrap it with [`create`](https://bench-zustand-6l.atloria.app/p/bench-zustand-6l-TzFgfybqJX/developer/zustand#create) to get a React store hook.

1. Define the state and action union. Each action has a string `type` and any data the reducer needs.
2. Write a pure reducer that takes the current state and action and returns the next state.
3. Pass the reducer and initial state to `redux`, then create a hook-backed store. The selected `dispatch` function accepts only the declared action union.

```tsx
import { create } from 'zustand'
import { redux } from 'zustand/middleware'
import { createRoot } from 'react-dom/client'

type AlertsState = {
  alertsEnabled: boolean
}

type AlertsAction =
  | { type: 'alerts/enable' }
  | { type: 'alerts/disable' }

type AlertsStore = AlertsState & {
  dispatch: (action: AlertsAction) => AlertsAction
}

function alertsReducer(
  state: AlertsState,
  action: AlertsAction,
): AlertsState {
  switch (action.type) {
    case 'alerts/enable':
      return { alertsEnabled: true }
    case 'alerts/disable':
      return { alertsEnabled: false }
    default:
      return state
  }
}

const initialState: AlertsState = { alertsEnabled: false }

const useAlertsStore = create<AlertsStore>()(
  redux(alertsReducer, initialState),
)

function AlertsSetting() {
  const alertsEnabled = useAlertsStore((state) => state.alertsEnabled)
  const dispatch = useAlertsStore((state) => state.dispatch)

  return (
    <section>
      <p>Alerts: {alertsEnabled ? 'On' : 'Off'}</p>
      <button onClick={() => dispatch({ type: 'alerts/enable' })}>
        Enable alerts
      </button>
      <button onClick={() => dispatch({ type: 'alerts/disable' })}>
        Disable alerts
      </button>
    </section>
  )
}

const container = document.createElement('div')
document.body.append(container)
createRoot(container).render(<AlertsSetting />)
```

![The initial Alerts: Off setting appears above the Enable alerts and Disable alerts buttons.](https://atloriaassets.blob.core.windows.net/assets/a438221c-c1af-407c-b9e6-a56c986db846/e3895c5f7a6b792908afe81e66b3238b.png)

The mounted control starts at **Alerts: Off**. Clicking **Enable alerts** dispatches its action and changes the display to **Alerts: On**; **Disable alerts** dispatches the action that displays **Alerts: Off**.

## Reducer and middleware inputs

`redux` has no configuration options here. It takes these two required inputs:

| Input | Type | Default | Effect |
| --- | --- | --- | --- |
| `reducer` | `(state: T, action: A) => T` | None | Computes the next state from the current state and an action. Keep it pure. |
| `initialState` | `T` | None | Provides the store's starting state; it cannot be a function. |

The middleware returns a state creator. Its `dispatch` function is available in the store state and on the store API, and calling it returns the dispatched action.

## Pitfalls

- Reducers and dispatched actions are optional in Zustand. For the colocated-action pattern without a reducer, see [Create and bind a React store](https://bench-zustand-6l.atloria.app/p/bench-zustand-6l-TzFgfybqJX/developer/create-and-bind-a-react-store).

## See it running

Try the [Zustand live demo](https://zustand-demo.pmnd.rs/).

## Related

- [How Zustand works](https://bench-zustand-6l.atloria.app/p/bench-zustand-6l-TzFgfybqJX/developer/how-zustand-works)
- [Middleware and composition](https://bench-zustand-6l.atloria.app/p/bench-zustand-6l-TzFgfybqJX/developer/middleware-and-composition)
- [Debug with Redux DevTools](https://bench-zustand-6l.atloria.app/p/bench-zustand-6l-TzFgfybqJX/developer/debug-with-redux-devtools)
