Skip to main content

zustand-5

Zustand 5 state management patterns. Trigger: When implementing client-side state with Zustand (stores, selectors, persist middleware, slices).

소스 정보

저장소
prowler-cloud/prowler
최근 소스 활동
2026년 1월 13일 10:44
감지된 SKILL.md 언어
영어
스타
14,884
포크
2,402

설치 방법

기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.

소스 파일 검토

설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.

SKILL.md 표시 중

SKILL.md
소스 지침 · 읽기 전용 미리보기
name
zustand-5
description
Zustand 5 state management patterns. Trigger: When implementing client-side state with Zustand (stores, selectors, persist middleware, slices).
license
Apache-2.0
metadata
{"author":"prowler-cloud","version":"1.0","scope":["root","ui"],"auto_invoke":"Using Zustand stores"}
allowed-tools
Read, Edit, Write, Glob, Grep, Bash, WebFetch, WebSearch, Task
## Basic Store ```typescript import { create } from "zustand"; interface CounterStore { count: number; increment: () => void; decrement: () => void; reset: () => void; } const useCounterStore = create<CounterStore>((set) => ({ count: 0, increment: () => set((state) => ({ count: state.count + 1 })), decrement: () => set((state) => ({ count: state.count - 1 })), reset: () => set({ count: 0 }), })); // Usage function Counter() { const { count, increment, decrement } = useCounterStore(); return ( <div> <span>{count}</span> <button onClick={increment}>+</button> <button onClick={decrement}>-</button> </div> ); } ``` ## Persist Middleware ```typescript import { create } from "zustand"; import { persist } from "zustand/middleware"; interface SettingsStore { theme: "light" | "dark"; language: string; setTheme: (theme: "light" | "dark") => void; setLanguage: (language: string) => void; } const useSettingsStore = create<SettingsStore>()( persist( (set) => ({ theme: "light", language: "en", setTheme: (theme) => set({ theme }), setLanguage: (language) => set({ language }), }), { name: "settings-storage", // localStorage key } ) ); ``` ## Selectors (Zustand 5) ```typescript // ✅ Select specific fields to prevent unnecessary re-renders function UserName() { const name = useUserStore((state) => state.name); return <span>{name}</span>; } // ✅ For multiple fields, use useShallow import { useShallow } from "zustand/react/shallow"; function UserInfo() { const { name, email } = useUserStore( useShallow((state) => ({ name: state.name, email: state.email })) ); return <div>{name} - {email}</div>; } // ❌ AVOID: Selecting entire store (causes re-render on any change) const store = useUserStore(); // Re-renders on ANY state change ``` ## Async Actions ```typescript interface UserStore { user: User | null; loading: boolean; error: string | null; fetchUser: (id: string) => Promise<void>; } const useUserStore = create<UserStore>((set) => ({ user: null, loading: false, error: null, fetchUser: async (id) => { set({ loading: true, error: null }); try { const response = await fetch(`/api/users/${id}`); const user = await response.json(); set({ user, loading: false }); } catch (error) { set({ error: "Failed to fetch user", loading: false }); } }, })); ``` ## Slices Pattern ```typescript // userSlice.ts interface UserSlice { user: User | null; setUser: (user: User) => void; clearUser: () => void; } const createUserSlice = (set): UserSlice => ({ user: null, setUser: (user) => set({ user }), clearUser: () => set({ user: null }), }); // cartSlice.ts interface CartSlice { items: CartItem[]; addItem: (item: CartItem) => void; removeItem: (id: string) => void; } const createCartSlice = (set): CartSlice => ({ items: [], addItem: (item) => set((state) => ({ items: [...state.items, item] })), removeItem: (id) => set((state) => ({ items: state.items.filter(i => i.id !== id) })), }); // store.ts type Store = UserSlice & CartSlice; const useStore = create<Store>()((...args) => ({ ...createUserSlice(...args), ...createCartSlice(...args), })); ``` ## Immer Middleware ```typescript import { create } from "zustand"; import { immer } from "zustand/middleware/immer"; interface TodoStore { todos: Todo[]; addTodo: (text: string) => void; toggleTodo: (id: string) => void; } const useTodoStore = create<TodoStore>()( immer((set) => ({ todos: [], addTodo: (text) => set((state) => { // Mutate directly with Immer! state.todos.push({ id: crypto.randomUUID(), text, done: false }); }), toggleTodo: (id) => set((state) => { const todo = state.todos.find(t => t.id === id); if (todo) todo.done = !todo.done; }), })) ); ``` ## DevTools ```typescript import { create } from "zustand"; import { devtools } from "zustand/middleware"; const useStore = create<Store>()( devtools( (set) => ({ // store definition }), { name: "MyStore" } // Name in Redux DevTools ) ); ``` ## Outside React ```typescript // Access store outside components const { count, increment } = useCounterStore.getState(); increment(); // Subscribe to changes const unsubscribe = useCounterStore.subscribe( (state) => console.log("Count changed:", state.count) ); ```
GitHub에서 보기