Skip to content
D
Documentation

Reset a store

how-to
2 min readUpdated

Reset a store to the state it had when it was created, or register reset callbacks to reset several stores together.

Reset one store

Use a colocated reset action when one store owns the reset. This example focuses on the reset action: for the mounted counter-and-button setup, see Debug with Redux DevTools. The mounted editor below changes its draft, then restores the original text when you click Reset.

Put this in src/main.tsx in a React app with a <div id="root"></div> mount point. Create the store with create, then render a component that selects the draft and its actions:

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

type DraftStore = {
  draft: string
  edit: () => void
  reset: () => void
}

const useDraftStore = create<DraftStore>()((set, _get, store) => ({
  draft: 'Draft starts here',
  edit: () => set({ draft: 'Edited draft' }),
  reset: () => set(store.getInitialState()),
}))

function DraftEditor() {
  const draft = useDraftStore((state) => state.draft)
  const edit = useDraftStore((state) => state.edit)
  const reset = useDraftStore((state) => state.reset)

  return (
    <main>
      <p>Draft: {draft}</p>
      <button onClick={edit}>Edit draft</button>
      <button onClick={reset}>Reset</button>
    </main>
  )
}

const rootElement = document.getElementById('root')
if (!rootElement) {
  throw new Error('Missing #root mount point')
}

createRoot(rootElement).render(<DraftEditor />)
The mounted editor displays its initial draft above the Edit draft and Reset buttons.

The reset action returns no value and restores the draft to its initial text. getInitialState() reads the state captured when the store is created; the action follows the authors' reset pattern of passing that state to set.

Reset multiple stores

For a coordinated reset, keep a set of callbacks and add one callback for each store. This React example starts two counters at different values. Clicking Reset all calls every registered callback, and both displayed counts return to their initial values.

Put this alternative in src/main.tsx:

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

type CounterStore = {
  count: number
  increment: () => void
}

const useFirstStore = create<CounterStore>()((set) => ({
  count: 1,
  increment: () => set((state) => ({ count: state.count + 1 })),
}))

const useSecondStore = create<CounterStore>()((set) => ({
  count: 10,
  increment: () => set((state) => ({ count: state.count + 1 })),
}))

const storeResetFns = new Set<() => void>()

storeResetFns.add(() =>
  useFirstStore.setState(useFirstStore.getInitialState(), true),
)
storeResetFns.add(() =>
  useSecondStore.setState(useSecondStore.getInitialState(), true),
)

function resetAllStores() {
  storeResetFns.forEach((resetFn) => {
    resetFn()
  })
}

function Counters() {
  const firstCount = useFirstStore((state) => state.count)
  const incrementFirst = useFirstStore((state) => state.increment)
  const secondCount = useSecondStore((state) => state.count)
  const incrementSecond = useSecondStore((state) => state.increment)

  return (
    <main>
      <p>First count: {firstCount}</p>
      <button onClick={incrementFirst}>Increment first</button>
      <p>Second count: {secondCount}</p>
      <button onClick={incrementSecond}>Increment second</button>
      <button onClick={resetAllStores}>Reset all</button>
    </main>
  )
}

const rootElement = document.getElementById('root')
if (!rootElement) {
  throw new Error('Missing #root mount point')
}

createRoot(rootElement).render(<Counters />)
The mounted page displays two counters and buttons to increment each counter or reset both.

Each registered callback calls setState with that store's initial state and true, so the state is replaced rather than shallowly merged. resetAllStores() returns no value; it invokes every callback in the set, and the mounted components render the restored counts.

Pitfalls

  • The single-store recipe calls set without the replace argument, so it uses Zustand's shallow merge. If the store can acquire keys that are not present in its initial state and the reset must remove them, use setState(initialState, true) as in the multi-store example.
  • A reset restores the initial state; it does not calculate a new baseline from current state. See Initialize state from props for initialization patterns.
  • For nested state, reset from the full initial nested value rather than constructing a partial nested object. See Update nested state for Zustand's one-level merge behavior.

Live demos

Was this page helpful?