Skip to content
masterclassBuddyTech Buzz5 fresh blogs · 5:00 AM IST

Zustand · Const

context provider pattern

The context provider pattern supplies a vanilla Zustand store through React context. A custom hook retrieves that store and uses selectors to subscribe components to the state they need.

How it works

The context provider pattern creates a vanilla Zustand store inside a React provider, supplies that store through React context, and wraps Zustand's useStore with a custom selector hook. This gives each provider subtree an independent store instance while preserving selective subscriptions.

Syntax

const StoreContext = createContext<StoreApi<State> | null>(null)
const [store] = useState(() => createStore(initializer))
return <StoreContext.Provider value={store}>{children}</StoreContext.Provider>
useStore(store, selector)

Key points

  • Use React context as the transport layer that makes a particular Zustand store available to descendants.
  • Separate provider instances can give separate component subtrees independent state rather than one shared global instance.
  • Wrap context access in a custom hook that accepts a selector and returns only the selected state value.
  • Connect the retrieved vanilla store to React by passing both the store and selector to Zustand's useStore.
  • Initialize the store lazily in state so the provider retains the same store object during rerenders.
  • Context is useful when multiple store instances must be managed and accessed through a component tree.

Common mistakes

  • Guard the custom hook against a missing provider so consumers fail clearly instead of attempting to use a null store.

Example: Context-backed Zustand store

import { createContext, useContext, useState, type ReactNode } from 'react'
import { createStore, useStore } from 'zustand'

type CounterState = { count: number; increment: () => void }
const createCounterStore = () => createStore<CounterState>((set) => ({
  count: 0,
  increment: () => set((state) => ({ count: state.count + 1 })),
}))

const CounterContext = createContext<ReturnType<typeof createCounterStore> | null>(null)
function CounterProvider({ children }: { children: ReactNode }) {
  const [store] = useState(createCounterStore)
  return <CounterContext.Provider value={store}>{children}</CounterContext.Provider>
}
function useCounter<T>(selector: (state: CounterState) => T) {
  const store = useContext(CounterContext)
  if (!store) throw new Error('Missing CounterProvider')
  return useStore(store, selector)
}
function Counter() {
  const count = useCounter((state) => state.count)
  const increment = useCounter((state) => state.increment)
  return <button onClick={increment}>{count}</button>
}
export function App() {
  return <CounterProvider><Counter /></CounterProvider>
}

Creates one vanilla store for the provider instance, exposes it through React context, and lets consumers select state with a custom hook.

When to use it

Independent widget state

A component subtree needs its own isolated store instance.

Prop-based initialization

Initial store values or behavior come from provider props.

Request-scoped state

A Next.js application must avoid sharing state across requests.

Context-managed store collections

Several keyed stores must be made available through one component hierarchy.

Interview questions

QHow does the context provider pattern work in Zustand?

Create a vanilla store with createStore, place it in a React context provider, and read it in a custom hook with useContext. The custom hook then calls Zustand's useStore(store, selector) so components subscribe to selected state.

Follow-up: Why create the store inside the provider? It gives each provider subtree an independent store instance and avoids unintentionally sharing state between separate trees.

QHow should the provider preserve the store instance?

A provider can initialize its store with useState(() => createStore(...)), which preserves one store instance for that provider across renders. Consumers retrieve the store from context and select only the state they need.

Follow-up: How would you support component props as initial state? Pass those props into the store factory used by the provider, then expose the resulting store through context.

QWhat safety checks and server-rendering concerns matter?

The custom hook should check whether useContext returned a store before calling useStore. If no store exists, it should throw an explicit error stating that the hook must be used within its provider.

Follow-up: What changes for Next.js? Create stores per request, avoid global stores, and do not read or write the store from React Server Components.

  • createStore
  • useStore
  • createContext
  • useContext
  • useState
  • initialize state with props

Source: useStore. Checked 2026-10-15.