بنقرة واحدة
zustand
Expert knowledge for client-side state management with Zustand using the decoupled actions pattern.
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
القائمة
Expert knowledge for client-side state management with Zustand using the decoupled actions pattern.
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
استنادا إلى تصنيف SOC المهني
Automates browser interactions for web testing, form filling, screenshots, and data extraction. Use when the user needs to navigate websites, interact with web pages, fill forms, take screenshots, test web applications, or extract information from web pages.
Best practices for building UI with shadcn/ui, Tailwind, and chart references.
Best practices for web project conventions built with Next.js, React, and TypeScript (structure, naming, imports, exports).
| name | zustand |
| description | Expert knowledge for client-side state management with Zustand using the decoupled actions pattern. |
Create Zustand stores following established patterns with proper TypeScript types and middleware.
Copy the template from assets/template.md and replace placeholders:
{{StoreName}} → PascalCase store name (e.g., Project){{description}} → Brief description for JSDoccreate() should define the state shape and initial values, not actions.store.setState(...).useState only for truly trivial, one-off UI toggles that do not justify a store.// web/store/use-example-store.ts
import { create } from "zustand";
interface ExampleState {
count: number;
items: string[];
}
// 1) Store definition (state only)
export const useExampleStore = create<ExampleState>(() => ({
count: 0,
items: [],
}));
// 2) Decoupled actions (exported individually)
export const increment = () => {
useExampleStore.setState((state) => ({ count: state.count + 1 }));
};
export const decrement = () => {
useExampleStore.setState((state) => ({ count: state.count - 1 }));
};
export const addItem = (item: string) => {
useExampleStore.setState((state) => ({ items: [...state.items, item] }));
};
export const reset = () => {
useExampleStore.setState({ count: 0, items: [] });
};
"use client";
import { increment, decrement, useExampleStore } from "@/store/use-example-store";
export function Counter() {
// Atomic selector: only re-renders when count changes
const count = useExampleStore((state) => state.count);
return (
<div>
<p>Count: {count}</p>
<button onClick={increment}>+</button>
<button onClick={decrement}>-</button>
</div>
);
}
useState only when the state is tiny, ephemeral, and unlikely to grow (e.g., a one-off boolean toggle).import { create } from "zustand";
import { subscribeWithSelector } from "zustand/middleware";
export const useMyStore = create<MyStore>()(
subscribeWithSelector((set, get) => ({
// state...
})),
);
export interface MyState {
items: Item[];
isLoading: boolean;
}
export interface MyActions {
addItem: (item: Item) => void;
loadItems: () => Promise<void>;
}
export type MyStore = MyState & MyActions;
// ✅ Correct: only re-renders when `items` changes
const items = useMyStore((state) => state.items);
// ❌ Avoid: re-renders on any state change
const { items, isLoading } = useMyStore();
Use functional updates when the new value depends on previous state:
// ✅ Correct: functional update
export const increment = () => {
useExampleStore.setState((state) => ({ count: state.count + 1 }));
};
// ❌ Avoid: reading state outside setState when updating
export const incrementBad = () => {
const current = useExampleStore.getState().count;
useExampleStore.setState({ count: current + 1 });
};
Select only what you need to prevent unnecessary re-renders:
// ✅ Correct: atomic selector
const count = useExampleStore((state) => state.count);
// ❌ Avoid: selecting entire state
const state = useExampleStore();
When you need multiple values, use separate selectors or shallow equality:
import { useShallow } from "zustand/react/shallow";
// Option 1: Multiple atomic selectors
const count = useExampleStore((state) => state.count);
const items = useExampleStore((state) => state.items);
// Option 2: useShallow for object selection
const { count, items } = useExampleStore(
useShallow((state) => ({ count: state.count, items: state.items })),
);
// ❌ Avoid: This will fail - Server Components cannot use client state
// app/page.tsx (Server Component)
import { useExampleStore } from "@/store/use-example-store";
// ✅ Correct: Pass data from Server Component to Client Component via props
// app/page.tsx
export default function Page() {
return <ClientCounter initialCount={0} />;
}
// ❌ Avoid: actions inside create
export const useStore = create<State & Actions>((set) => ({
count: 0,
increment: () => set((state) => ({ count: state.count + 1 })),
}));
// ✅ Correct: decoupled actions
export const useStore = create<State>(() => ({ count: 0 }));
export const increment = () => useStore.setState((s) => ({ count: s.count + 1 }));
Before completing any Zustand-related task:
'use client')create()bun run lint to verify no type errors