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:
tsximport { 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 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:
tsximport { 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 />)
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
setwithout 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, usesetState(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.
Was this page helpful?