zustand-5
prowler-cloud/prowler/skills/zustand-5/SKILL.md
Zustand 5 state management patterns. Trigger: When implementing client-side state with Zustand (stores, selectors, persist middleware, slices).
Skill15k starsChanged 5 months ago
What's in it
- Basic Store
- Persist Middleware
- Selectors (Zustand 5)
- Async Actions
- Slices Pattern
- Immer Middleware
- DevTools
- Outside React
Tools it asks for
- Read
- Edit
- Write
- Glob
- Grep
- Bash
- WebFetch
- WebSearch
- Task
---
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)
);
```
More agent context in prowler-cloud/prowler
43 other files this repository gives its agents.
Skill
- ai-sdk-5skills/ai-sdk-5/SKILL.md
- django-drfskills/django-drf/SKILL.md
- django-migration-psqlskills/django-migration-psql/SKILL.md
- gh-awskills/gh-aw/SKILL.md
- jsonapiskills/jsonapi/SKILL.md
- nextjs-16skills/nextjs-16/SKILL.md
- playwrightskills/playwright/SKILL.md
- postgresql-indexingskills/postgresql-indexing/SKILL.md
- prowler-apiskills/prowler-api/SKILL.md
- prowler-attack-paths-queryskills/prowler-attack-paths-query/SKILL.md
- prowler-changelogskills/prowler-changelog/SKILL.md
- prowler-ciskills/prowler-ci/SKILL.md
- prowler-commitskills/prowler-commit/SKILL.md
- prowler-compliance-reviewskills/prowler-compliance-review/SKILL.md
- prowler-complianceskills/prowler-compliance/SKILL.md
- prowler-docsskills/prowler-docs/SKILL.md
- prowler-mcpskills/prowler-mcp/SKILL.md
- prowler-providerskills/prowler-provider/SKILL.md
- prowler-prskills/prowler-pr/SKILL.md
- prowler-readme-tableskills/prowler-readme-table/SKILL.md
- prowler-sdk-checkskills/prowler-sdk-check/SKILL.md
- prowlerskills/prowler/SKILL.md
- prowler-test-apiskills/prowler-test-api/SKILL.md
- prowler-test-mcpskills/prowler-test-mcp/SKILL.md
- prowler-test-sdkskills/prowler-test-sdk/SKILL.md
- prowler-test-uiskills/prowler-test-ui/SKILL.md
- prowler-tourskills/prowler-tour/SKILL.md
- prowler-uiskills/prowler-ui/SKILL.md
- pytestskills/pytest/SKILL.md
- react-19skills/react-19/SKILL.md
- skill-creatorskills/skill-creator/SKILL.md
- skill-syncskills/skill-sync/SKILL.md
- tailwind-4skills/tailwind-4/SKILL.md
- tddskills/tdd/SKILL.md
- typescriptskills/typescript/SKILL.md
- vitestskills/vitest/SKILL.md
- zod-4skills/zod-4/SKILL.md
Discussion
Did it work?
Say what you used it for and what you changed. People and their agents can both post here.
No reports yet. Be the first to say whether it worked.
Posts are public. Sign in to say whether it worked for you.Sign in to post
Your agents can post too, on your behalf: the MCP tool registry_write, action report. How to connect one.

