webroad.online
  1. 1Веб
  2. 2HTML
  3. 3CSS
  4. 4JavaScript
  5. 5TypeScript
  6. 6Git
  7. 7Инструменты
  8. 8React
  9. 9Стейт-менеджмент
  10. 10Next.js
  11. 11Формы
  12. 12Данные и бэкенд
  13. 13SEO
  14. 14Tailwind CSS
  15. 15Анимации
  16. 16Тестирование
  17. 17Архитектура
Стейт-менеджмент · Урок 3 из 4

Zustand

Минималистичный глобальный стор: create, set со слиянием, селекторы, persist.

Обновлено

Что такое Zustand

Zustand — маленькая (~1 КБ) библиотека для глобального состояния: стор создаётся функцией и используется как хук. Без провайдера, без строковых типов действий, без редьюсеров — только состояние и функции, которые его меняют.

import { create } from 'zustand'

type CartState = {
  items: number[]
  add: (id: number) => void
  clear: () => void
}

export const useCart = create<CartState>()(set => ({
  items: [],
  add: id => set(state => ({ items: [...state.items, id] })),
  clear: () => set({ items: [] }),
}))
'use client'
const count = useCart(state => state.items.length)   // селектор
const add = useCart(state => state.add)
<button onClick={() => add(product.id)}>Добавить</button>

Как это работает

  • create возвращает хук. Стор живёт вне React; компоненты на него подписываются.
  • set сливает (merge) новый объект с текущим состоянием на первом уровне — копировать всё не нужно.
  • Компонент перерисовывается, только когда меняется значение, которое возвращает селектор.

Селекторы — самая важная деталь

Код Перерисовка, когда
useCart() (без селектора) меняется что угодно в сторе ✗
useCart(s => s.items.length) только когда меняется количество ✓
useCart(s => ({ a: s.a, b: s.b })) всегда — новый объект на каждом рендере ✗
useCart(useShallow(s => ({ a: s.a, b: s.b }))) когда меняется a или b ✓

Правило: выбирайте как можно меньше; для нескольких значений — несколько вызовов или useShallow.

Полезные middleware

import { persist, devtools } from 'zustand/middleware'

export const useSettings = create<Settings>()(
  persist(
    set => ({ theme: 'light', setTheme: theme => set({ theme }) }),
    { name: 'settings' },                 // ключ в localStorage
  ),
)
Middleware Что делает
persist сохраняет стор в localStorage / sessionStorage
devtools подключает Redux DevTools
immer «мутабельный» синтаксис, как в RTK

Zustand или Redux Toolkit

Zustand Redux Toolkit
Код для простого стора ~10 строк слайс + стор + провайдер + типизированные хуки
Провайдер не нужен нужен
Навязанная структура мало — решаете сами много — слайсы, действия
Серверное состояние нет (используйте TanStack Query) RTK Query в комплекте
Подходит для большинства приложений больших приложений, команд, которым нужны строгие правила

Zustand с Next.js

Глобальный стор на уровне модуля на сервере общий для всех запросов. Правила:

  • Используйте стор только в Client Components.
  • Не кладите туда данные конкретного пользователя при серверном рендере; для этого создавайте стор на запрос (createStore + Context) — паттерн описан в официальном гайде.
  • С persist значение из localStorage появляется только после гидратации.

Где он лежит в FSD

Стор, связанный с сущностью → entities/cart/model/cart-store.ts. Глобальный UI-стор → shared/model/ или слайс, которому он принадлежит.

Коротко

  • Zustand = create → хук; set сливает; без провайдера.
  • Маленькие селекторы; useShallow для нескольких значений.
  • persist для localStorage; в Next — только на клиенте, осторожно с данными конкретного пользователя.

Официальные источники

Упражнения

Была ли страница полезной?

Один клик — без регистрации.