Token导航 LogoToken导航

Agent Skill · 研究检索

zustand-store-patterns(zustand 商店模式)

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

zustand-store-patterns 是研究检索类 Agent Skill,可用宿主为 Codex、Claude、Cursor、Gemini CLI,通过GitHub 仓库获取,权限为需要联网;许可证为 MIT,第三方扫描有未通过项,按安装量在研究检索类的 73,675 个 Skill 里排第 48,042。

总安装 706周安装 30GitHub Stars 142下载 247核验 2026-05-01

安装说明

本站只整理中文说明,不托管安装包,也不代用户安装。
GitHub
许可证
MIT

安装方式

通过对话安装

复制提示词发给支持本地命令或 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

这个 Skill 是做什么的

研究检索类 Skill 主要解决「找资料、核对事实、把来源整理清楚」的问题,通常会让助手先检索再总结。

zustand-store-patterns 用于查找、检索和筛选相关信息。适合在 Codex、Claude、Cursor、Gemini CLI 中根据关键词或任务场景快速定位候选结果。通过 npx skills add 命令从指定 GitHub 仓库安装使用。

安装前需确认权限范围、维护状态,以及是否会触发联网、命令执行或文件读写。建议结合原始 README 核验具体用法和功能边界。

来源仓库内路径:skills/zustand-store-patterns

上手步骤

4 步
  1. 1

    确认自己的宿主工具

    公开资料标注支持 Codex、Claude、Cursor、Gemini CLI;先确认自己用的是其中之一,再按对应工具的 Skills 目录放置。

  2. 2

    拿到安装命令

    可以直接复制的命令是 npx skills add https://github.com/thebushidocollective/han --skill zustand-store…;命令里的占位符换成自己的路径或密钥再执行。

  3. 3

    安装后重启宿主

    命令执行完要完全退出宿主工具再打开,让新装的 Skill 被重新扫描到,否则列表里可能看不到。

  4. 4

    按最小权限试用

    它需要需要联网,先在测试目录或测试账号里跑,确认没问题再放到正式项目。

常见问题

6 条

zustand-store-patterns 怎么安装?

在终端执行 npx skills add https://github.com/thebushidocollective/han --skill zustand-store-patterns。装完完全退出宿主工具再打开,让它重新扫描本地 Skill。

zustand-store-patterns 支持哪些 AI 工具?

公开资料标注支持 Codex、Claude、Cursor、Gemini CLI。其他工具只要能读取本地 Skill 目录,一般也能手动放进去,但要自己确认触发方式是否一致。

zustand-store-patterns 需要什么权限?

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

zustand-store-patterns 是免费的吗?

来源标注的许可证是 MIT。本站不代收任何费用,也不托管安装包;能否商用、要不要署名,以许可证原文为准。

zustand-store-patterns 用的人多吗?

公开数据是累计安装 706 次,近一周安装 30 次,下载 247 次,GitHub 142 星。这些数字来自第三方目录统计,只能当作热度参考,不代表质量或安全性。

zustand-store-patterns 安全吗?

第三方扫描有未通过项,风险较高。除非你确认过源码,否则不建议直接安装到常用环境。

值得选的地方和要先想清楚的地方

值得选的地方

  • 同时适配 4 种工具,换客户端不用重新找替代品。
  • 3 个目录同时收录,说明这个 Skill 流传比较广。
  • 许可证明确为 MIT,商用和分发边界好判断。

先想清楚的地方

  • 第三方扫描存在提醒项或未通过项,需要人工逐条确认。
  • 第三方目录整理,版本更新和行为细节以来源仓库为准。

适不适合你

更适合

  • 已经在用 Codex,想直接扩展它能力的人。
  • 需要处理研究检索类任务、又不想每次都手写提示词的人。

不太适合

  • 需要厂商级技术支持和 SLA 的生产系统。

研究检索类 Skill 对比

6 个同类
Skill总安装GitHub 星权限许可证扫描
find-skills

寻找技能 · Codex、Claude

31,199,81316,486操作浏览器MIT有提醒
self-improving-agent

自我改进 Agent · OpenClaw

16,464,0023,396接触敏感数据MIT-0通过
soultrace

灵魂追踪 · Codex、Claude

7,588,94412需要联网未明确有提醒
self-improving

自我完善 · OpenClaw

6,829,2841,046需要联网MIT-0通过
microsoft-foundry

微软代工厂 · Codex、Claude

6,614,144764调用外部服务未明确有提醒
zustand-store-patterns

zustand 商店模式 · 本页

706142需要联网MIT未通过

按安装量取同分类前几名;数字来自第三方目录统计,只作热度参考,不代表质量结论。

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

平台分布

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 复核。

安装前确认

本站仅展示第三方公开信息,不托管安装包,不提供自动安装或运行环境。安装前应自行审查源码、依赖和命令行为。来源安全扫描存在提醒或未通过项,安装前请自行复核。

继续浏览同类 Skills