Token导航 LogoToken导航TokenDH.com
研究检索需要联网github未标认证来源可访问clear审计异常

zustand-store-patternszustand 商店模式

Agent Skill

zustand-store-patterns 用于查找、检索和筛选相关信息,适合在 Codex、Claude、Cursor、Gemini CLI 中需要根据关键词、任务场景或来源线索快速定位候选结果时使用。可结合来源仓库、安装命令和原始 README 继续核验具体用法。安装前建议确认权限范围、维护状态,以及是否会触发联网、命令执行或文件读写。

总安装

706

周安装

30

GitHub Stars

142

下载量

247
CodexClaudeCursorGemini CLI

安装说明

本站只整理中文说明和来源信息,不托管安装包,也不代用户安装。

GitHub

来源数

3

许可证

MIT

最后核验

2026-05-01

来源状态

来源可访问

安装方式

通过对话安装

复制提示词发给支持本地命令或 Skills 的 AI 助手,先确认命令和权限,再让它执行。

请帮我安装这个 Agent Skill:zustand-store-patterns(zustand 商店模式)
来源仓库:https://github.com/thebushidocollective/han
仓库路径:skills/zustand-store-patterns
安装命令:
npx skills add https://github.com/thebushidocollective/han --skill zustand-store-patterns
安装前请先检查当前环境是否支持对应 CLI,并向我确认将要执行的命令、安装目录、联网范围和文件读写权限;确认后再执行。

命令行安装

复制命令到本机终端执行。不同来源提供的安装方式可能略有差异;本站展示可直接复制的安装命令,安装前请核对来源页面。

skills.shnpx skills
npx skills add https://github.com/thebushidocollective/han --skill zustand-store-patterns

简介

zustand-store-patterns 用于查找、检索和筛选相关信息。

  • 适合在 Codex、Claude、Cursor、Gemini CLI 中根据关键词或任务场景快速定位候选结果。
  • 通过 npx skills add 命令从指定 GitHub 仓库安装使用。
  • 安装前需确认权限范围、维护状态,以及是否会触发联网、命令执行或文件读写。
  • 建议结合原始 README 核验具体用法和功能边界。

SKILL.md

Zustand - Store Patterns

Zustand is a small, fast, and scalable state management solution for React. It uses a simplified flux principles with a hooks-based API.

Key Concepts

Store Creation

A Zustand store is created using the create function:

import { create } from 'zustand'

interface BearStore {
  bears: number
  increasePopulation: () => void
  removeAllBears: () => void
}

const useBearStore = create<BearStore>((set) => ({
  bears: 0,
  increasePopulation: () => set((state) => ({ bears: state.bears + 1 })),
  removeAllBears: () => set({ bears: 0 }),
}))

Using the Store in Components

function BearCounter() {
  const bears = useBearStore((state) => state.bears)
  return <h1>{bears} around here...</h1>
}

function Controls() {
  const increasePopulation = useBearStore((state) => state.increasePopulation)
  return <button onClick={increasePopulation}>Add bear</button>
}

State Updates

Zustand provides two ways to update state:

// Replace state
set({ bears: 5 })

// Merge state (shallow merge)
set((state) => ({ bears: state.bears + 1 }))

Best Practices

1. Use Selectors for Performance

Select only the state you need to prevent unnecessary re-renders:

// ❌ Bad: Component re-renders on any state change
function BadComponent() {
  const store = useBearStore()
  return <div>{store.bears}</div>
}

// ✅ Good: Component only re-renders when bears changes
function GoodComponent() {
  const bears = useBearStore((state) => state.bears)
  return <div>{bears}</div>
}

2. Separate Actions from State

Keep your store organized by separating data from actions:

interface TodoStore {
  // State
  todos: Todo[]
  filter: 'all' | 'active' | 'completed'

  // Actions
  addTodo: (text: string) => void
  toggleTodo: (id: string) => void
  removeTodo: (id: string) => void
  setFilter: (filter: TodoStore['filter']) => void
}

const useTodoStore = create<TodoStore>((set) => ({
  todos: [],
  filter: 'all',

  addTodo: (text) =>
    set((state) => ({
      todos: [...state.todos, { id: Date.now().toString(), text, completed: false }],
    })),

  toggleTodo: (id) =>
    set((state) => ({
      todos: state.todos.map((todo) =>
        todo.id === id ? { ...todo, completed: !todo.completed } : todo
      ),
    })),

  removeTodo: (id) =>
    set((state) => ({
      todos: state.todos.filter((todo) => todo.id !== id),
    })),

  setFilter: (filter) => set({ filter }),
}))

3. Use Shallow Equality for Multiple Selectors

When selecting multiple values, use shallow from zustand/shallow:

import { create } from 'zustand'
import { shallow } from 'zustand/shallow'

const useStore = create<Store>((set) => ({
  nuts: 0,
  honey: 0,
  increaseNuts: () => set((state) => ({ nuts: state.nuts + 1 })),
  increaseHoney: () => set((state) => ({ honey: state.honey + 1 })),
}))

// ✅ Using shallow comparison
function Component() {
  const { nuts, honey } = useStore(
    (state) => ({ nuts: state.nuts, honey: state.honey }),
    shallow
  )
  return <div>{nuts} nuts, {honey} honey</div>
}

4. Organize Large Stores with Slices

For complex applications, split stores into logical slices:

interface UserSlice {
  user: User | null
  login: (credentials: Credentials) => Promise<void>
  logout: () => void
}

interface CartSlice {
  items: CartItem[]
  addItem: (item: Product) => void
  removeItem: (id: string) => void
  clearCart: () => void
}

const createUserSlice = (set: StateCreator<UserSlice>) => ({
  user: null,
  login: async (credentials) => {
    const user = await api.login(credentials)
    set({ user })
  },
  logout: () => set({ user: null }),
})

const createCartSlice = (set: StateCreator<CartSlice>) => ({
  items: [],
  addItem: (product) =>
    set((state) => ({
      items: [...state.items, { ...product, quantity: 1 }],
    })),
  removeItem: (id) =>
    set((state) => ({
      items: state.items.filter((item) => item.id !== id),
    })),
  clearCart: () => set({ items: [] }),
})

const useStore = create<UserSlice & CartSlice>()((...a) => ({
  ...createUserSlice(...a),
  ...createCartSlice(...a),
}))

5. Access Store Outside Components

Use getState and setState for non-reactive access:

const useBearStore = create<BearStore>((set, get) => ({
  bears: 0,
  increasePopulation: () => set((state) => ({ bears: state.bears + 1 })),
  doSomething: () => {
    const currentBears = get().bears
    console.log(`Current bears: ${currentBears}`)
  },
}))

// Outside components
const currentState = useBearStore.getState()
useBearStore.setState({ bears: 10 })

Examples

Simple Counter Store

import { create } from 'zustand'

interface CounterStore {
  count: number
  increment: () => void
  decrement: () => void
  reset: () => void
}

export 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, reset } = useCounterStore()

  return (
    <div>
      <h1>Count: {count}</h1>
      <button onClick={increment}>+</button>
      <button onClick={decrement}>-</button>
      <button onClick={reset}>Reset</button>
    </div>
  )
}

Shopping Cart Store

import { create } from 'zustand'

interface CartItem {
  id: string
  name: string
  price: number
  quantity: number
}

interface CartStore {
  items: CartItem[]
  addItem: (product: Omit<CartItem, 'quantity'>) => void
  removeItem: (id: string) => void
  updateQuantity: (id: string, quantity: number) => void
  clearCart: () => void
  total: number
}

export const useCartStore = create<CartStore>((set, get) => ({
  items: [],

  addItem: (product) =>
    set((state) => {
      const existingItem = state.items.find((item) => item.id === product.id)

      if (existingItem) {
        return {
          items: state.items.map((item) =>
            item.id === product.id
              ? { ...item, quantity: item.quantity + 1 }
              : item
          ),
        }
      }

      return {
        items: [...state.items, { ...product, quantity: 1 }],
      }
    }),

  removeItem: (id) =>
    set((state) => ({
      items: state.items.filter((item) => item.id !== id),
    })),

  updateQuantity: (id, quantity) =>
    set((state) => ({
      items: state.items.map((item) =>
        item.id === id ? { ...item, quantity } : item
      ),
    })),

  clearCart: () => set({ items: [] }),

  get total() {
    return get().items.reduce(
      (sum, item) => sum + item.price * item.quantity,
      0
    )
  },
}))

Authentication Store

import { create } from 'zustand'

interface User {
  id: string
  email: string
  name: string
}

interface AuthStore {
  user: User | null
  token: string | null
  isLoading: boolean
  error: string | null

  login: (email: string, password: string) => Promise<void>
  logout: () => void
  checkAuth: () => Promise<void>
}

export const useAuthStore = create<AuthStore>((set) => ({
  user: null,
  token: null,
  isLoading: false,
  error: null,

  login: async (email, password) => {
    set({ isLoading: true, error: null })

    try {
      const response = await fetch('/api/login', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({ email, password }),
      })

      if (!response.ok) {
        throw new Error('Login failed')
      }

      const { user, token } = await response.json()
      set({ user, token, isLoading: false })
      localStorage.setItem('token', token)
    } catch (error) {
      set({
        error: error instanceof Error ? error.message : 'Login failed',
        isLoading: false,
      })
    }
  },

  logout: () => {
    localStorage.removeItem('token')
    set({ user: null, token: null })
  },

  checkAuth: async () => {
    const token = localStorage.getItem('token')
    if (!token) return

    set({ isLoading: true })

    try {
      const response = await fetch('/api/me', {
        headers: { Authorization: `Bearer ${token}` },
      })

      if (!response.ok) {
        throw new Error('Auth check failed')
      }

      const user = await response.json()
      set({ user, token, isLoading: false })
    } catch (error) {
      localStorage.removeItem('token')
      set({ user: null, token: null, isLoading: false })
    }
  },
}))

Common Patterns

Computed Values

Use getters for derived state:

const useStore = create<Store>((set, get) => ({
  items: [],

  get itemCount() {
    return get().items.length
  },

  get hasItems() {
    return get().items.length > 0
  },
}))

Async Actions

Handle async operations within actions:

const useStore = create<Store>((set) => ({
  data: null,
  isLoading: false,
  error: null,

  fetchData: async () => {
    set({ isLoading: true, error: null })

    try {
      const data = await api.fetchData()
      set({ data, isLoading: false })
    } catch (error) {
      set({ error: error.message, isLoading: false })
    }
  },
}))

Reset Store

Implement a reset action:

const initialState = {
  count: 0,
  name: '',
}

const useStore = create<Store>((set) => ({
  ...initialState,

  increment: () => set((state) => ({ count: state.count + 1 })),
  setName: (name: string) => set({ name }),
  reset: () => set(initialState),
}))

Anti-Patterns

❌ Don't Mutate State Directly

// Bad
const useStore = create((set) => ({
  items: [],
  addItem: (item) => {
    // DON'T mutate state directly
    items.push(item)
  },
}))

// Good
const useStore = create((set) => ({
  items: [],
  addItem: (item) =>
    set((state) => ({
      items: [...state.items, item],
    })),
}))

❌ Don't Select the Entire Store

// Bad: Causes re-render on any state change
const store = useStore()

// Good: Select only what you need
const count = useStore((state) => state.count)

❌ Don't Use External State in Selectors

// Bad: Selector depends on external value
const [userId, setUserId] = useState('123')
const user = useStore((state) => state.users[userId])

// Good: Pass external values as arguments
const getUser = (userId: string) => useStore.getState().users[userId]

❌ Don't Create Multiple Stores for Related Data

// Bad: Splitting related state across stores
const useUserStore = create(...)
const useUserSettingsStore = create(...)
const useUserPreferencesStore = create(...)

// Good: Keep related state together
const useUserStore = create((set) => ({
  profile: null,
  settings: {},
  preferences: {},
}))

Related Skills

  • zustand-typescript: TypeScript integration and type safety patterns
  • zustand-middleware: Using persist, devtools, and immer middleware
  • zustand-advanced-patterns: Subscriptions, transient updates, and advanced techniques

适合场景

01

用户想查找某类 Agent Skill 时

02

需要根据任务场景推荐可安装能力包时

03

需要对比不同来源的安装命令和来源信息时

04

需要参考平台分布和安装热度时

能力概览

能力 1

按任务关键词查找相关 Skills

能力 2

展示可复制的安装命令

能力 3

保留来源站点、仓库和原始说明,方便继续核验

能力 4

补充不同宿主或平台的使用分布数据

能力 5

展示第三方安全扫描或审计结果

安装后应在对应宿主中按原始 README 的触发条件使用;具体调用方式请以来源页面和 README 为准。

平台分布

Codex

28.85%
按下载量换算71

Claude Code

23.19%
按下载量换算57

Antigravity

17.78%
按下载量换算44

OpenCode

11.56%
按下载量换算29

windsurf

6.82%
按下载量换算17

trae

3.01%
按下载量换算7

安全审计

Gen Agent Trust Hub

未通过

Socket

通过

Snyk

通过

权限和风险

需要联网

该 Skill 可能需要联网访问来源站点、仓库或外部 API;具体网络访问范围需要结合源码和 README 复核。

安装前确认

本站仅展示第三方公开信息,不托管安装包,不提供自动安装或运行环境。安装前应自行审查源码、依赖和命令行为。来源安全扫描存在 warning/failed 结果,不能写成本站确认安全。

来源信息

继续浏览同类 Skills