patterntypescriptreactTip
Zustand basics — minimal global store without providers
Viewed 0 times
zustandcreatestoreselectorno providerglobal stateminimal redux
Problem
Redux requires a Provider wrapper, boilerplate reducers, and action creators. For small-to-medium apps, this overhead is disproportionate. Zustand offers a simpler mental model: a hook-based store with no provider required.
Solution
Create a typed store with create and use it directly in components:
import { create } from 'zustand';
interface BearState {
bears: number;
name: string;
increment: () => void;
setName: (name: string) => void;
reset: () => void;
}
const initialState = { bears: 0, name: '' };
export const useBearStore = create<BearState>((set) => ({
...initialState,
increment: () => set((state) => ({ bears: state.bears + 1 })),
setName: (name) => set({ name }),
reset: () => set(initialState),
}));
// Component — subscribe to only what you need
function BearCounter() {
const bears = useBearStore((state) => state.bears);
const increment = useBearStore((state) => state.increment);
return <button onClick={increment}>Bears: {bears}</button>;
}
import { create } from 'zustand';
interface BearState {
bears: number;
name: string;
increment: () => void;
setName: (name: string) => void;
reset: () => void;
}
const initialState = { bears: 0, name: '' };
export const useBearStore = create<BearState>((set) => ({
...initialState,
increment: () => set((state) => ({ bears: state.bears + 1 })),
setName: (name) => set({ name }),
reset: () => set(initialState),
}));
// Component — subscribe to only what you need
function BearCounter() {
const bears = useBearStore((state) => state.bears);
const increment = useBearStore((state) => state.increment);
return <button onClick={increment}>Bears: {bears}</button>;
}
Why
Zustand stores are plain JS objects with functions. Selecting slices of state with selector functions prevents unnecessary re-renders — a component only re-renders when its selected slice changes.
Gotchas
- Selecting the whole store object (useStore()) causes re-renders on every state change — always use selectors
- Actions defined inside create close over set/get — do not destructure them outside the create call
- Zustand does not use React context by default — stores are module-level singletons, which simplifies testing but requires care with server-side rendering
- For SSR (Next.js), create stores inside a React context or use createStore (not create) to avoid shared state across requests
Revisions (0)
No revisions yet.