Skip to content
D
Documentation

Persist selected state

how-to
1 min readUpdated

Use partialize when a persisted store contains both user state and runtime-only state. The function returns the slice that persist writes; the rest of the store remains available during the current session but is rebuilt from its initial value after a reload.

Choose the persisted fields

This example keeps the selected item across reloads but does not store the draft text. It uses create with a React hook and the default JSON storage backed by localStorage.

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

type Item = {
  id: string
  label: string
}

type AppStore = {
  selectedId: string | null
  draft: string
  select: (id: string) => void
  setDraft: (draft: string) => void
}

type PersistedAppStore = Pick<AppStore, 'selectedId'>

const items: Item[] = [
  { id: 'alpha', label: 'Alpha' },
  { id: 'beta', label: 'Beta' },
]

const useAppStore = create<AppStore>()(
  persist<AppStore, [], [], PersistedAppStore>(
    (set) => ({
      selectedId: null,
      draft: '',
      select: (selectedId) => set({ selectedId }),
      setDraft: (draft) => set({ draft }),
    }),
    {
      name: 'selected-item-demo',
      partialize: (state): PersistedAppStore => ({
        selectedId: state.selectedId,
      }),
    },
  ),
)

function App() {
  const selectedId = useAppStore((state) => state.selectedId)
  const draft = useAppStore((state) => state.draft)
  const select = useAppStore((state) => state.select)
  const setDraft = useAppStore((state) => state.setDraft)

  return (
    <main>
      <h1>Items</h1>
      <p>Selected: {selectedId ?? 'none'}</p>
      <ul>
        {items.map((item) => (
          <li key={item.id}>
            <button type="button" onClick={() => select(item.id)}>
              Select {item.label}
            </button>
          </li>
        ))}
      </ul>
      <label>
        Draft note
        <input
          value={draft}
          onChange={(event) => setDraft(event.target.value)}
        />
      </label>
    </main>
  )
}

const root = document.getElementById('root')!

createRoot(root).render(
  <StrictMode>
    <App />
  </StrictMode>,
)
The mounted example shows the item list, the current selection, and the draft note field.

Clicking a selection updates the rendered Selected value and writes only selectedId under the selected-item-demo storage key. Type text into Draft note, then reload: the selected item remains and the draft returns to its initial empty value. The persisted value contains the state returned by partialize, not the store's actions or the omitted draft field.

partialize options that matter

OptionTypeDefaultWhat it does
namestring—Chooses the unique storage key.
partialize(state: State) => PersistedState(state) => stateSelects the value written to storage.
storagePersistStorage<PersistedState>createJSONStorage(() => localStorage)Supplies the storage adapter used for reads and writes.

Return an object containing the fields you intend to restore. If the persisted selection is part of a nested object, read Merge persisted state before partially persisting it: the default merge is shallow and can replace an entire nested object. If the adapter is asynchronous, the first render can show defaults while hydration completes; see Persist store data.

Was this page helpful?