Skip to main content

zustand-5

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

Aller à l'installation

Informations de source

Dépôt
prowler-cloud/prowler
Dernière activité de la source
13 janvier 2026 à 10:44
Langue détectée de SKILL.md
anglais
Étoiles
14 842
Forks
2 391

Options d'installation

Le prompt qui vérifie d'abord la source est sélectionné par défaut. Vous pouvez passer à une commande directe ou télécharger une copie locale.

Vérifiez les fichiers source

Lisez SKILL.md et les fichiers associés affichés par SkillsMP avant de décider de l'installer.

Affichage de SKILL.md

SKILL.md
Instructions source · Aperçu en lecture seule
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) ); ```
Voir sur GitHub