Flux inspired practice

Although Zustand is an unopinionated library, we do recommend a few patterns. These are inspired by practices originally found in Flux, and more recently Redux, so if you are coming from another library, you should feel right at home.

However, Zustand does differ in some fundamental ways, so some terminology may not perfectly align to other libraries.

Single store

Your applications global state should be located in a single Zustand store.

If you have a large application, Zustand supports splitting the store into slices.

Use set / setState to update the store

Always use set (or setState) to perform updates to your store. set (and setState) ensures the described update is correctly merged and listeners are appropriately notified.

Colocate store actions

In Zustand, state can be updated without the use of dispatched actions and reducers found in other Flux libraries. These store actions can be added directly to the store as shown below.

Optionally, by using setState they can be located external to the store

const useBoundStore = create((set) => ({
  storeSliceA: ...,
  storeSliceB: ...,
  storeSliceC: ...,
  updateX: () => set(...),
  updateY: () => set(...),
}))

Redux-like patterns

If you can't live without Redux-like reducers, you can define a dispatch function on the root level of the store:

const types = { increase: 'INCREASE', decrease: 'DECREASE' }

const reducer = (state, { type, by = 1 }) => {
  switch (type) {
    case types.increase:
      return { grumpiness: state.grumpiness + by }
    case types.decrease:
      return { grumpiness: state.grumpiness - by }
  }
}

const useGrumpyStore = create((set) => ({
  grumpiness: 0,
  dispatch: (args) => set((state) => reducer(state, args)),
}))

const dispatch = useGrumpyStore((state) => state.dispatch)
dispatch({ type: types.increase, by: 2 })

You could also use our redux-middleware. It wires up your main reducer, sets initial state, and adds a dispatch function to the state itself and the vanilla api.

import { redux } from 'zustand/middleware'

const useReduxStore = create(redux(reducer, initialState))

Another way to update the store could be through functions wrapping the state functions. These could also handle side-effects of actions. For example, with HTTP-calls. To use Zustand in a non-reactive way, see the readme.