zustand-5

>

INSTALLATION
npx skills add https://github.com/prowler-cloud/prowler --skill zustand-5
Run in your project or agent environment. Adjust flags if your CLI version differs.

SKILL.md

$27

// Usage

function Counter() {

const { count, increment, decrement } = useCounterStore();

return (

{count}

+

-

);

}

## Persist Middleware

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)

// ✅ 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

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

// 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 &#x26; CartSlice;

const useStore = create<Store>()((...args) => ({

...createUserSlice(...args),

...createCartSlice(...args),

}));


## Immer Middleware

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

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

// Access store outside components

const { count, increment } = useCounterStore.getState();

increment();

// Subscribe to changes

const unsubscribe = useCounterStore.subscribe(

(state) => console.log("Count changed:", state.count)

);

BrowserAct

Let your agent run on any real-world website

Bypass CAPTCHA & anti-bot for free. Start local, scale to cloud.

Explore BrowserAct Skills →

Stop writing automation&scrapers

Install the CLI. Run your first Skill in 30 seconds. Scale when you're ready.

Start free
free · no credit card