Learn / Frameworks / React / App-wide State with Zustand

React · Lesson 13 of 15

App-wide State with Zustand

Share global state without wrapping the tree in providers.

  • Intermediate
  • 16 min read
  • 3 objectives

Before this lessonLesson 12: Testing Components

What you will learn

  • Create a store
  • Select slices
  • Know when Context is enough

Your Progress

0 of 15 lessons 0%

  • Lessons0 / 15
  • Completed0
  • Est. time left~ 4 hours

Create a free account to keep your progress on every device.

Context is enough for a theme or the current user. For frequent updates (a cart, a filter panel, a long form) it re-renders every consumer. A small store library such as Zustand lets components subscribe to just the slice they need.

A store

npm install zustand
// store/cart.js
import { create } from "zustand";

export const useCart = create((set, get) => ({
  items: [],
  add: (item) => set((s) => ({ items: [...s.items, item] })),
  remove: (id) => set((s) => ({ items: s.items.filter((i) => i.id !== id) })),
  total: () => get().items.reduce((n, i) => n + i.price, 0),
}));

Select a slice

function CartCount() {
  const count = useCart((s) => s.items.length);   // re-renders only when length changes
  return <span>{count}</span>;
}

function AddButton({ product }) {
  const add = useCart((s) => s.add);
  return <button onClick={() => add(product)}>Add</button>;
}

Selecting the whole store (useCart() with no argument) re-renders on every change. Always pick a field or a stable action.

When not to add a library

  • State used by one component or a parent and its children: useState.
  • Rarely changing values (locale, auth user): Context is simpler.
  • Server data (lists from an API): TanStack Query, not a client store.
// Write your solution here
Up next · Lesson 14Component PatternsCompound components, portals, forwarding refs and composition that scales.