본문으로 건너뛰기
cccskills
무료GitHub에 공개

web-state-zustand

Zustand stores, client state patterns. Use when deciding between Zustand vs useState, managing global state, or avoiding Context misuse.

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

설치 방법 보기

포함된 파일(4)

  • SKILL.md7.7 KB
  • examples/core.md5.2 KB
  • metadata.yaml382 B
  • reference.md2.0 KB

SKILL.md(원문)

설치하기 전에 에이전트에게 전달되는 지시 내용을 확인할 수 있습니다.

Zustand Patterns

Quick Guide: Zustand owns state two or more components read; useState owns state one component reads; the URL owns filters and search; Context injects singletons and holds no state. Zustand v5 changes three things: useShallow from zustand/react/shallow replaces the old equality-function second argument, selectors must return stable references or they loop, and persist no longer captures initial state at creation.

Detailed Resources:

  • examples/core.md — store setup, atomic selectors, useShallow, the Context anti-pattern, URL state
  • reference.md — middleware lookup, v5 migration notes, peer-dependency requirements

<critical_requirements>

Before writing Zustand code

Move a value into a store as soon as a second component reads it. Passing it down instead couples every component on the path, and relocating it later means unpicking that chain.

Select one value per useStore call. The component then re-renders when that value changes and at no other time; a call with no selector subscribes to the whole store.

Return a stable reference from every selector. An object or function built inside the selector is a new reference on each call, which in v5 re-renders without end.

Persist preferences and nothing else, through partialize. Transient UI restored from storage — a modal that reopens itself, a sidebar that remembers being closed — reads as a bug.

Keep server data out of the store. Cached, invalidated, refetched data wants a layer built for it; a store gives you a copy that goes stale silently.

</critical_requirements>


Auto-detection: create from zustand, zustand/middleware, zustand/react/shallow, useShallow, createWithEqualityFn, zustand/traditional, persist, partialize, devtools, store slices

Applies to:

  • Choosing between a store, useState, the URL and Context for a given value
  • Setting up a store with devtools and persist
  • Selector shape and re-render behaviour
  • Splitting state across focused stores

Handled elsewhere:

  • Server data — caching, invalidation and refetching belong to whatever owns the network, and a store is not that thing
  • Routing mechanics — this skill says which state belongs in the URL, not how a given router reads or writes it
  • Form field state — a form library owns its own field values while the form is open

<philosophy>

Zustand is a subscription primitive with a hook attached. Its performance comes entirely from the selector: the store notifies every subscriber on every change, and the selector is what decides whether that notification becomes a render. So store design is selector design.

  • Small stores over one large one — a store is the unit of subscription as well as the unit of code
  • Business logic in actions — components call toggleSidebar(); the store decides what toggling means
  • Export hooks, not the creator — the raw store is a mutable global, and exporting it invites writes from anywhere
  • Atomic selectors first — a single value needs no comparison function at all
</philosophy>

<decision_framework>

Where a value belongs

The valueBelongs inBecause
Read by 2+ componentsa storeselective re-renders, and no prop chain to unpick later
Read by 1 componentuseStatenothing else can observe it, so nothing else needs to
A filter, query, page or sortthe URLshareable, bookmarkable, and the back button works
A singleton set at startupContextit never changes, so the re-render cost never arises
Fetched from an APInot this skillit needs caching and invalidation, which a store has none of

Context is the row people get wrong. It is a transport for a value that does not change, and using it for state that does re-renders every consumer on every change with no way to opt out.

</decision_framework>


<patterns>

Core patterns

Pattern 1: Store Setup

devtools for inspection, persist for the fields that should outlive the tab, partialize to keep everything else out of storage.

export const useUIStore = create<UIState>()(
  devtools(
    persist(
      (set) => ({
        theme: DEFAULT_THEME,
        sidebarOpen: true,
        toggleSidebar: () =>
          set((state) => ({ sidebarOpen: !state.sidebarOpen })),
      }),
      { name: UI_STORAGE_KEY, partialize: (state) => ({ theme: state.theme }) },
    ),
  ),
);

Full code: examples/core.md

Pattern 2: Atomic Selectors

One value per call is the default, and the reason the store is fast.

const toggleSidebar = useUIStore((state) => state.toggleSidebar);
const isOpen = useUIStore((state) => state.sidebarOpen);

Full code: examples/core.md

Pattern 3: useShallow for Multiple Values

At three or more values from one store, one useShallow call beats three subscriptions.

import { useShallow } from "zustand/react/shallow";

const { sidebarOpen, theme } = useUIStore(
  useShallow((state) => ({
    sidebarOpen: state.sidebarOpen,
    theme: state.theme,
  })),
);

Full code: examples/core.md

Pattern 4: Context for Injection, Not State

Context carries a value that never changes — a client, a connection, a configuration read at startup.

const DatabaseContext = createContext<Database | null>(null);

Full code: examples/core.md

Pattern 5: URL State for Shareable Filters

Filters, search, pagination and sort live in the URL, where they survive a reload and a paste into a colleague's chat.

const searchParams = new URLSearchParams(window.location.search);
const category = searchParams.get("category") ?? undefined;

Full code: examples/core.md

</patterns>

<red_flags>

Red flags

Breaks at runtime:

  • A selector returning an inline object or function — new reference every call, so v5 re-renders without end. Hoist the fallback to a module constant.
  • create() called with a second equality-function argument — removed in v5, so the argument is ignored and the comparison silently never happens. Use useShallow, or createWithEqualityFn from zustand/traditional.
  • Reading a computed initial value back out of a persisted store immediately after creation — v5's persist did not store it. Set it with setState after creation.

Surprising behaviour:

  • useStore() with no selector subscribes to the entire store, so the component re-renders on changes to fields it never reads.
  • Two atomic selectors returning equal values still render separately if either changes; useShallow compares the object, not the individual reads.
  • Context re-renders every consumer whenever the provider's value object is rebuilt, which is every render unless the value is memoised — and even memoised, a change to one field re-renders readers of all of them.
  • Search params are strings. ?page=2 reads back as "2", and ?open=false is truthy until parsed.
  • One large store means one large subscription surface: every component reading from it competes with every write to it.

</red_flags>

리뷰

아직 리뷰가 없습니다. 사용해 본 소감을 남겨 주세요.

댓글

로그인 없이 쓸 수 있습니다. 사용 후기, 질문, 작동하지 않은 환경 등을 편하게 남겨 주세요.

아직 댓글이 없습니다. 첫 댓글을 남겨 보세요.

보내면 바로 공개됩니다. 이메일 주소나 전화번호 같은 개인 정보는 쓰지 마세요. URL은 2개까지입니다.

0 / 1,000자

이 양식은 reCAPTCHA로 보호되며 Google 개인정보처리방침 및 서비스 약관이 적용됩니다.

같은 저장소의 스킬

Hugging Face Inference SDK patterns for TypeScript/Node.js — InferenceClient setup, chat completion, text generation, streaming, embeddings, image generation, audio transcription, translation, summarization, and Inference Endpoints

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

agents-inc/skills252026년 10월 17일 업데이트

LiteLLM proxy server setup, TypeScript client patterns via OpenAI SDK, model routing, fallbacks, load balancing, spend tracking, virtual keys, and production deployment

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

agents-inc/skills252026년 10월 17일 업데이트

Serverless GPU compute platform for AI model deployment — web endpoints, GPU functions, model serving, and TypeScript client patterns

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

agents-inc/skills252026년 10월 17일 업데이트

Local LLM inference with the Ollama JavaScript client -- chat, streaming, tool calling, vision, embeddings, structured output, model management, and OpenAI-compatible endpoint

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

agents-inc/skills252026년 10월 17일 업데이트

Replicate SDK patterns for TypeScript/Node.js -- client setup, predictions, streaming, webhooks, file handling, model versioning, deployments, and training

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

agents-inc/skills252026년 10월 17일 업데이트

Together AI SDK patterns for TypeScript — client setup, chat completions, streaming, structured output, function calling, embeddings, image generation, fine-tuning, and OpenAI-compatible endpoints

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

agents-inc/skills252026년 10월 17일 업데이트

agents-inc의 스킬 모두 보기

이 스킬의 문제 신고