intermediate

Store slices

Split larger stores into cohesive slices while keeping action ownership and cross-slice dependencies clear.

Large Zustand stores split into slices — factory functions that receive `set`, `get`, and merge into one `create` state. Each slice owns actions and state fields for a feature.

					import { create } from 'zustand';

const createBearSlice = (set) => ({
  bears: 0,
  addBear: () => set((s) => ({ bears: s.bears + 1 })),
});

const createFishSlice = (set) => ({
  fish: 0,
  addFish: () => set((s) => ({ fish: s.fish + 1 })),
});

const useStore = create((...args) => ({
  ...createBearSlice(...args),
  ...createFishSlice(...args),
}));
				

Cross-slice reads use `get()` inside actions. Avoid circular dependencies between slices; extract shared helpers when needed.

The trade-off is modular stores versus coordination cost when slices share derived or persisted fields.

On interviews: slice boundaries versus multiple separate stores.

Common pitfalls: slices mutating each other's shape informally, name collisions on merge, and god-slice anti-pattern.

Checklist:

  • One create with composed slices.
  • Clear action ownership per slice.
  • get() for cross-slice coordination.
  • Split stores only when lifecycles differ.