### Demonstrate Zustand Provider and Custom Hook Usage in React Source: https://zustand.docs.pmnd.rs/guides/initialize-state-with-props This example shows a complete application setup using the `BearProvider` wrapper component to initialize the store with props and a `HookConsumer` (presumably `CommonConsumer` from previous examples) that uses the custom `useBearContext` hook. ```javascript // Provider wrapper & custom hook consumer function App2() { return ( ) } ``` -------------------------------- ### Install `use-sync-external-store` for Zustand v5 Source: https://zustand.docs.pmnd.rs/migrations/migrating-to-v5 This command shows the necessary installation step for `use-sync-external-store`, which becomes a peer dependency in Zustand v5. This package is required when using `createWithEqualityFn` and `useStoreWithEqualityFn` from `zustand/traditional`. ```bash npm install use-sync-external-store ``` -------------------------------- ### Complete Example: Zustand Store with useStoreWithEqualityFn in React Source: https://zustand.docs.pmnd.rs/hooks/use-store-with-equality-fn This comprehensive example combines the creation of a Zustand vanilla store with its consumption in a React component using `useStoreWithEqualityFn`. It includes the store definition, the `MovingDot` component that updates position with `shallow` equality, and the root `App` component. This demonstrates a full, runnable setup for managing and reacting to state changes efficiently in React. ```tsx import { createStore } from 'zustand' import { useStoreWithEqualityFn } from 'zustand/traditional' import { shallow } from 'zustand/shallow' type PositionStoreState = { position: { x: number; y: number } } type PositionStoreActions = { setPosition: (nextPosition: PositionStoreState['position']) => void } type PositionStore = PositionStoreState & PositionStoreActions const positionStore = createStore()((set) => ({ position: { x: 0, y: 0 }, setPosition: (position) => set({ position }), })) function MovingDot() { const position = useStoreWithEqualityFn( positionStore, (state) => state.position, shallow, ) const setPosition = useStoreWithEqualityFn( positionStore, (state) => state.setPosition, shallow, ) return (
{ setPosition({ x: e.clientX, y: e.clientY, }) }} style={{ position: 'relative', width: '100vw', height: '100vh', }} >
) } export default function App() { return } ``` -------------------------------- ### Per-Route Store Provider Setup in Next.js Pages Router Source: https://zustand.docs.pmnd.rs/guides/nextjs Demonstrates how to create a store per route by wrapping the page component with the CounterStoreProvider at the page level. This approach is useful when you need isolated store instances for different routes. ```typescript // src/pages/index.tsx import { CounterStoreProvider } from '@/providers/counter-store-provider.tsx' import { HomePage } from '@/components/pages/home-page.tsx' export default function Home() { return ( ) } ``` -------------------------------- ### Complete Zustand Versioned Persistence Example Source: https://zustand.docs.pmnd.rs/middlewares/persist Full working example combining store creation, migration logic, localStorage initialization, event handling, and DOM updates. Demonstrates end-to-end implementation of versioned state persistence with real-time mouse tracking and visual feedback. ```typescript import { createStore } from 'zustand/vanilla' import { persist } from 'zustand/middleware' if (!localStorage.getItem('position-storage')) { localStorage.setItem( 'position-storage', JSON.stringify({ state: { x: 100, y: 100 }, version: 0, }), ) } type PositionStoreState = { position: { x: number; y: number } } type PositionStoreActions = { setPosition: (nextPosition: PositionStoreState['position']) => void } type PositionStore = PositionStoreState & PositionStoreActions const positionStore = createStore()( persist( (set) => ({ position: { x: 0, y: 0 }, setPosition: (position) => set({ position }), }), { name: 'position-storage', version: 1, migrate: (persisted: any, version) => { if (version === 0) { persisted.position = { x: persisted.x, y: persisted.y } delete persisted.x delete persisted.y } return persisted }, }, ), ) const $dotContainer = document.getElementById('dot-container') as HTMLDivElement const $dot = document.getElementById('dot') as HTMLDivElement $dotContainer.addEventListener('pointermove', (event) => { positionStore.getState().setPosition({ x: event.clientX, y: event.clientY, }) }) const render: Parameters[0] = (state) => { $dot.style.transform = `translate(${state.position.x}px, ${state.position.y}px)` } render(positionStore.getState(), positionStore.getState()) positionStore.subscribe(render) ``` -------------------------------- ### Complete Example of Dynamic Scoped Zustand Stores in React Source: https://zustand.docs.pmnd.rs/hooks/use-store This combined code snippet provides a comprehensive view of the core setup for dynamic, scoped Zustand stores within a React application. It includes necessary React and Zustand imports, the definition of the counter store types, the `createCounterStore` factory, the `createCounterStoreFactory` for managing instances, and the `CounterStoresContext` setup. ```typescript import { type ReactNode, useState, useCallback, useContext, createContext, } from 'react' import { createStore, useStore } from 'zustand' type CounterState = { count: number } type CounterActions = { increment: () => void } type CounterStore = CounterState & CounterActions const createCounterStore = () => { return createStore()((set) => ({ count: 0, increment: () => { set((state) => ({ count: state.count + 1 })) }, })) } const createCounterStoreFactory = ( counterStores: Map>, ) => { return (counterStoreKey: string) => { if (!counterStores.has(counterStoreKey)) { counterStores.set(counterStoreKey, createCounterStore()) } return counterStores.get(counterStoreKey)! } } const CounterStoresContext = createContext > | null>(null) ``` -------------------------------- ### Install Zustand package using NPM Source: https://zustand.docs.pmnd.rs/getting-started/introduction This command installs the Zustand state management library into your project using the Node Package Manager (NPM). It adds Zustand as a dependency, allowing you to import and use its functionalities. Requires Node.js and NPM to be installed. ```bash npm install zustand ``` -------------------------------- ### HTML Structure for Age Store Example Source: https://zustand.docs.pmnd.rs/apis/create-store HTML markup for the age store example featuring a heading to display current age and two buttons to increment the age by different amounts. ```html

``` -------------------------------- ### HTML for Zustand Object Position Example Source: https://zustand.docs.pmnd.rs/apis/create-store This HTML snippet provides the basic structure for a visual representation of the object state update example. It includes a container ('dot-container') that listens for pointer movements and a movable element ('dot') whose position is controlled by the Zustand store. ```html
``` -------------------------------- ### Complete Example: Scoped Zustand Stores for Independent React Component State Source: https://zustand.docs.pmnd.rs/hooks/use-store-with-equality-fn This comprehensive code block provides a full, runnable example demonstrating the implementation of independent Zustand stores in a React application. It integrates store definition, context provision, a custom hook for state access, and a component utilizing this setup, culminating in an `App` component that renders multiple instances with isolated state. This example includes all necessary imports and setup for a functional application. ```typescript import { type ReactNode, useState, createContext, useContext } from 'react' import { createStore } from 'zustand' import { useStoreWithEqualityFn } from 'zustand/traditional' import { shallow } from 'zustand/shallow' type PositionStoreState = { position: { x: number; y: number } } type PositionStoreActions = { setPosition: (nextPosition: PositionStoreState['position']) => void } type PositionStore = PositionStoreState & PositionStoreActions const createPositionStore = () => { return createStore()((set) => ({ position: { x: 0, y: 0 }, setPosition: (position) => set({ position }), })) } const PositionStoreContext = createContext | null>(null) function PositionStoreProvider({ children }: { children: ReactNode }) { const [store] = useState(() => createPositionStore()) return ( {children} ) } function usePositionStore(selector: (state: PositionStore) => U) { const store = useContext(PositionStoreContext) if (store === null) { throw new Error( 'usePositionStore must be used within PositionStoreProvider', ) } return useStoreWithEqualityFn(store, selector, shallow) } function MovingDot({ color }: { color: string }) { const position = usePositionStore((state) => state.position) const setPosition = usePositionStore((state) => state.setPosition) return (
{ setPosition({ x: e.clientX > e.currentTarget.clientWidth ? e.clientX - e.currentTarget.clientWidth : e.clientX, y: e.clientY, }) }} style={{ position: 'relative', width: '50vw', height: '100vh', }} >
) } export default function App() { return (
) } ``` -------------------------------- ### Complete Global Vanilla Zustand Store Integration Example Source: https://zustand.docs.pmnd.rs/hooks/use-store This comprehensive example provides a full, runnable code block demonstrating the end-to-end integration of a Zustand vanilla store with a React application. It includes the store definition with TypeScript types, a React component consuming and updating the store's state, and the root App component for a complete interactive experience. ```typescript import { createStore, useStore } from 'zustand' type PositionStoreState = { position: { x: number; y: number } } type PositionStoreActions = { setPosition: (nextPosition: PositionStoreState['position']) => void } type PositionStore = PositionStoreState & PositionStoreActions const positionStore = createStore()((set) => ({ position: { x: 0, y: 0 }, setPosition: (position) => set({ position }), })) function MovingDot() { const position = useStore(positionStore, (state) => state.position) const setPosition = useStore(positionStore, (state) => state.setPosition) return (
{ setPosition({ x: e.clientX, y: e.clientY, }) }} style={{ position: 'relative', width: '100vw', height: '100vh', }} >
) } export default function App() { return } ``` -------------------------------- ### HTML structure for the interactive dot example Source: https://zustand.docs.pmnd.rs/middlewares/combine Provides the necessary HTML markup for the interactive dot example, including a container (`dot-container`) and a movable dot element (`dot`). Both elements are styled using inline CSS to demonstrate their initial appearance and positioning. ```html
``` -------------------------------- ### Complete Zustand URL Persistence Example in TypeScript Source: https://zustand.docs.pmnd.rs/middlewares/persist This comprehensive TypeScript example integrates all components: URL search parameter utilities, the custom storage adapter, the Zustand store definition with persistence, and the UI interaction logic. It provides a full, runnable solution for a state-persisted, interactive component that uses URL parameters for state management. ```typescript import { createStore } from 'zustand/vanilla' import { persist, createJSONStorage } from 'zustand/middleware' type PositionStoreState = { position: { x: number; y: number } } type PositionStoreActions = { setPosition: (nextPosition: PositionStoreState['position']) => void } type PositionStore = PositionStoreState & PositionStoreActions const getSearchParams = () => { return new URL(location.href).searchParams } const updateSearchParams = (searchParams: URLSearchParams) => { window.history.replaceState( {}, '', `${location.pathname}?${searchParams.toString()}`, ) } const getSearchParam = (key: string) => { const searchParams = getSearchParams() return searchParams.get(key) } const updateSearchParam = (key: string, value: string) => { const searchParams = getSearchParams() searchParams.set(key, value) updateSearchParams(searchParams) } const removeSearchParam = (key: string) => { const searchParams = getSearchParams() searchParams.delete(key) updateSearchParams(searchParams) } const searchParamsStorage = { getItem: (key: string) => getSearchParam(key), setItem: (key: string, value: string) => updateSearchParam(key, value), removeItem: (key: string) => removeSearchParam(key), } const positionStore = createStore()( persist( (set) => ({ position: { x: 0, y: 0 }, setPosition: (position) => set({ position }), }), { name: 'position-storage', storage: createJSONStorage(() => searchParamsStorage), }, ), ) ``` -------------------------------- ### Install Immer Package Source: https://zustand.docs.pmnd.rs/integrations/immer-middleware Install Immer as a direct dependency to use the Immer middleware with Zustand. This is a required prerequisite for enabling Immer functionality. ```bash npm install immer ``` -------------------------------- ### Setup Root Layout with Zustand Provider Source: https://zustand.docs.pmnd.rs/guides/nextjs Configures the Next.js App Router root layout to wrap the application with CounterStoreProvider. Imports metadata, fonts, and global styles. The provider wraps all children components, making the Zustand store accessible throughout the application hierarchy. ```typescript import type { Metadata } from 'next' import { Inter } from 'next/font/google' import './globals.css' import { CounterStoreProvider } from '@/providers/counter-store-provider' const inter = Inter({ subsets: ['latin'] }) export const metadata: Metadata = { title: 'Create Next App', description: 'Generated by create next app', } export default function RootLayout({ children, }: Readonly<{ children: React.ReactNode }>) { return ( {children} ) } ``` -------------------------------- ### Use Zustand Store in React Components with TypeScript Selectors Source: https://zustand.docs.pmnd.rs/guides/beginner-typescript This example illustrates how to consume a Zustand store within a React functional component. It shows selecting specific state parts (`s.bears`) to optimize re-renders and leverage TypeScript for autocompletion and type safety when accessing store properties. ```typescript import { useBearStore } from './store' function BearCounter() { // Select only 'bears' to avoid unnecessary re-renders const bears = useBearStore((s) => s.bears) return

{bears} bears around

} ``` -------------------------------- ### Create and Use Multiple Zustand Stores with TypeScript Source: https://zustand.docs.pmnd.rs/guides/beginner-typescript This snippet demonstrates how to define and use multiple independent Zustand stores (`useBearStore` and `useFishStore`) within a React component. It showcases the use of TypeScript interfaces for strict type checking, ensuring state isolation and preventing accidental mixing of data. The example includes state definition, actions to modify state, and a functional component (`Zoo`) that consumes both stores. ```typescript import { create } from 'zustand' // Bear store with explicit types interface BearState { bears: number addBear: () => void } const useBearStore = create()((set) => ({ bears: 2, addBear: () => set((s) => ({ bears: s.bears + 1 })), })) // Fish store with explicit types interface FishState { fish: number addFish: () => void } const useFishStore = create()((set) => ({ fish: 5, addFish: () => set((s) => ({ fish: s.fish + 1 })), })) // In components, you can use both stores safely function Zoo() { const { bears, addBear } = useBearStore() const { fish, addFish } = useFishStore() return (
{bears} bears and {fish} fish
) } ``` -------------------------------- ### Setup Counter Store Provider in Next.js Pages Router _app.tsx Source: https://zustand.docs.pmnd.rs/guides/nextjs Configures the Zustand store provider at the application level in Next.js Pages Router using the _app.tsx file. This wraps all pages with the provider, making the store accessible throughout the application. ```typescript // src/_app.tsx import type { AppProps } from 'next/app' import { CounterStoreProvider } from '@/providers/counter-store-provider.tsx' export default function App({ Component, pageProps }: AppProps) { return ( ) } ``` -------------------------------- ### Configure Vitest Setup File for Jest-like Auto-Mocking Source: https://zustand.docs.pmnd.rs/guides/testing This setup file for Vitest imports `@testing-library/jest-dom/vitest` for Jest-DOM matchers and configures `vi.mock('zustand')` to enable Jest-like auto-mocking for Zustand. This ensures that Zustand modules are automatically mocked, allowing for easier testing of components that depend on Zustand stores. If Vitest globals are not enabled, `import { vi } from 'vitest'` must be added. ```typescript import '@testing-library/jest-dom/vitest' vi.mock('zustand') // to make it work like Jest (auto-mocking) ``` -------------------------------- ### Configure Vitest for JSDOM Environment and Setup Files Source: https://zustand.docs.pmnd.rs/guides/testing This Vitest configuration file extends the base Vite configuration and sets up the testing environment. It enables global APIs (`globals: true`), specifies `jsdom` as the test environment, and points to `./setup-vitest.ts` as the file to run before each test suite. This ensures a browser-like environment and consistent test setup for all tests. ```typescript import { defineConfig, mergeConfig } from 'vitest/config' import viteConfig from './vite.config' export default defineConfig((configEnv) => mergeConfig( viteConfig(configEnv), defineConfig({ test: { globals: true, environment: 'jsdom', setupFiles: ['./setup-vitest.ts'], }, }), ), ) ``` -------------------------------- ### Next.js Pages Router Home Page with Store Provider Source: https://zustand.docs.pmnd.rs/guides/nextjs Shows the basic home page component structure in Next.js Pages Router that renders the HomePage component. This is the entry point for the application. ```typescript // src/pages/index.tsx import { HomePage } from '@/components/pages/home-page.tsx' export default function Home() { return } ``` -------------------------------- ### Example with as Parameters workaround for dynamic replace flag in Zustand (TypeScript) Source: https://zustand.docs.pmnd.rs/guides/advanced-typescript A complete example demonstrating the application of the `as Parameters` workaround for dynamically setting the `replace` flag in `setState`. It initializes a basic Zustand store and then shows how to call `setState` with dynamically determined arguments while maintaining type correctness. ```typescript import { create } from 'zustand' interface BearState { bears: number increase: (by: number) => void } const useBearStore = create()((set) => ({ bears: 0, increase: (by) => set((state) => ({ bears: state.bears + by })), })) const replaceFlag = Math.random() > 0.5 const args = [{ bears: 5 }, replaceFlag] as Parameters< typeof useBearStore.setState > useBearStore.setState(...args) // Using the workaround ``` -------------------------------- ### Create Store with subscribeWithSelector Middleware Source: https://zustand.docs.pmnd.rs/middlewares/subscribe-with-selector Demonstrates how to create a Zustand store with the subscribeWithSelector middleware applied. The example creates a position store that tracks x and y coordinates with a setter method. The middleware enables subscribing to specific state slices like position or position.x. ```typescript import { createStore } from 'zustand/vanilla' import { subscribeWithSelector } from 'zustand/middleware' type PositionStoreState = { position: { x: number; y: number } } type PositionStoreActions = { setPosition: (nextPosition: PositionStoreState['position']) => void } type PositionStore = PositionStoreState & PositionStoreActions const positionStore = createStore()( subscribeWithSelector((set) => ({ position: { x: 0, y: 0 }, setPosition: (position) => set({ position }), })), ) ``` -------------------------------- ### Async Actions in Zustand for Remote Data Fetching Source: https://zustand.docs.pmnd.rs/guides/beginner-typescript Demonstrates how to define async actions that fetch remote data and update store state. TypeScript enforces correct API response types and prevents runtime errors from property misspellings. ```TypeScript import { create } from 'zustand' interface BearData { count: number } interface BearState { bears: number fetchBears: () => Promise } export const useBearStore = create()((set) => ({ bears: 0, fetchBears: async () => { const res = await fetch('/api/bears') const data: BearData = await res.json() set({ bears: data.count }) }, })) ``` -------------------------------- ### Create Counter Store with Redux Source: https://zustand.docs.pmnd.rs/getting-started/comparison Shows two Redux approaches: basic Redux with createStore and a reducer function, and Redux Toolkit with createSlice for simplified state management. Both examples demonstrate action dispatching and state selection for render optimization. ```TypeScript import { createStore } from 'redux' import { useSelector, useDispatch } from 'react-redux' type State = { count: number } type Action = { type: 'increment' | 'decrement' qty: number } const countReducer = (state: State, action: Action) => { switch (action.type) { case 'increment': return { count: state.count + action.qty } case 'decrement': return { count: state.count - action.qty } default: return state } } const countStore = createStore(countReducer) const Component = () => { const count = useSelector((state) => state.count) const dispatch = useDispatch() // ... } ``` -------------------------------- ### Import and Render Home Page Component Source: https://zustand.docs.pmnd.rs/guides/nextjs A simple page component that imports and renders the HomePage component. This is the default export for the root route in Next.js App Router, serving as the entry point for the application. ```typescript import { HomePage } from '@/components/pages/home-page' export default function Home() { return } ``` -------------------------------- ### Create Zustand Store Hook Source: https://zustand.docs.pmnd.rs/index Initialize a Zustand store using the create function. The store is a hook that accepts a function with a set parameter for state updates. The set function merges state changes, allowing you to define state properties and action methods. ```javascript import { create } from 'zustand' const useBear = create((set) => ({ bears: 0, increasePopulation: () => set((state) => ({ bears: state.bears + 1 })), removeAllBears: () => set({ bears: 0 }), updateBears: (newBears) => set({ bears: newBears }), })) ``` -------------------------------- ### Combine Middleware for Zustand State and Actions Source: https://zustand.docs.pmnd.rs/guides/beginner-typescript Illustrates the combine middleware pattern that separates initial state from actions, improving code organization and enabling automatic TypeScript type inference. This approach eliminates the need for explicit interfaces and is popular in TypeScript projects. ```TypeScript import { create } from 'zustand' import { combine } from 'zustand/middleware' interface BearState { bears: number increase: () => void } // State + actions are separated export const useBearStore = create()( combine({ bears: 0 }, (set) => ({ increase: () => set((s) => ({ bears: s.bears + 1 })), })), ) ``` -------------------------------- ### Creating a Zustand store with `combine` and inferred types Source: https://zustand.docs.pmnd.rs/middlewares/combine Demonstrates how to create a Zustand store using `createStore` and the `combine` middleware. This example shows automatic type inference for the store's state and actions, and includes an interactive UI update based on mouse movement, showcasing state management in action. ```typescript import { createStore } from 'zustand/vanilla' import { combine } from 'zustand/middleware' const positionStore = createStore( combine({ position: { x: 0, y: 0 } }, (set) => ({ setPosition: (position) => set({ position }), })), ) const $dotContainer = document.getElementById('dot-container') as HTMLDivElement const $dot = document.getElementById('dot') as HTMLDivElement $dotContainer.addEventListener('pointermove', (event) => { positionStore.getState().setPosition({ x: event.clientX, y: event.clientY, }) }) const render: Parameters[0] = (state) => { $dot.style.transform = `translate(${state.position.x}px, ${state.position.y}px)` } render(positionStore.getInitialState(), positionStore.getInitialState()) positionStore.subscribe(render) ``` -------------------------------- ### Handle storage hydration with onRehydrateStorage callback Source: https://zustand.docs.pmnd.rs/integrations/persisting-store-data Example of using the onRehydrateStorage option to monitor and handle the hydration process. The callback logs hydration start, completion, and any errors that occur during state restoration from storage. ```javascript export const useBoundStore = create( persist( (set, get) => ({ // ... }), { // ... onRehydrateStorage: (state) => { console.log('hydration starts') // optional return (state, error) => { if (error) { console.log('an error happened during hydration', error) } else { console.log('hydration finished') } } }, }, ), ) ``` -------------------------------- ### Complete Scoped Zustand Store Implementation in React Source: https://zustand.docs.pmnd.rs/hooks/use-store This comprehensive code block provides the full implementation for creating and using scoped Zustand stores in a React application. It includes all necessary imports, store definition, context and provider setup, custom hook for access, and the `MovingDot` and `App` components, demonstrating a complete, working example. ```typescript import { type ReactNode, useState, createContext, useContext } from 'react' import { createStore, useStore } from 'zustand' type PositionStoreState = { position: { x: number; y: number } } type PositionStoreActions = { setPosition: (nextPosition: PositionStoreState['position']) => void } type PositionStore = PositionStoreState & PositionStoreActions const createPositionStore = () => { return createStore()((set) => ({ position: { x: 0, y: 0 }, setPosition: (position) => set({ position }), })) } const PositionStoreContext = createContext | null>(null) function PositionStoreProvider({ children }: { children: ReactNode }) { const [store] = useState(() => createPositionStore()) return ( {children} ) } function usePositionStore(selector: (state: PositionStore) => U) { const store = useContext(PositionStoreContext) if (store === null) { throw new Error( 'usePositionStore must be used within PositionStoreProvider', ) } return useStore(store, selector) } function MovingDot({ color }: { color: string }) { const position = usePositionStore((state) => state.position) const setPosition = usePositionStore((state) => state.setPosition) return (
{ setPosition({ x: e.clientX > e.currentTarget.clientWidth ? e.clientX - e.currentTarget.clientWidth : e.clientX, y: e.clientY, }) }} style={{ position: 'relative', width: '50vw', height: '100vh', }} >
) } ``` -------------------------------- ### Complete Zustand Application with Persistence and UI Interaction Source: https://zustand.docs.pmnd.rs/middlewares/persist This comprehensive snippet combines all the previous parts into a single, runnable TypeScript code block. It includes the Zustand store setup with `persist` and `skipHydration`, the DOM event listener for updating state on pointer movement, the manual rehydration logic, and the store subscription for rendering UI changes, providing a full example of a persistent, interactive application. ```typescript import { createStore } from 'zustand/vanilla' import { persist } from 'zustand/middleware' type PositionStoreState = { position: { x: number; y: number } } type PositionStoreActions = { setPosition: (nextPosition: PositionStoreState['position']) => void } type PositionStore = PositionStoreState & PositionStoreActions const positionStore = createStore()( persist( (set) => ({ position: { x: 0, y: 0 }, setPosition: (position) => set({ position }), }), { name: 'position-storage', skipHydration: true, }, ), ) const $dotContainer = document.getElementById('dot-container') as HTMLDivElement const $dot = document.getElementById('dot') as HTMLDivElement $dotContainer.addEventListener('pointermove', (event) => { positionStore.getState().setPosition({ x: event.clientX, y: event.clientY, }) }) const render: Parameters[0] = (state) => { $dot.style.transform = `translate(${state.position.x}px, ${state.position.y}px)` } setTimeout(() => { positionStore.persist.rehydrate() }, 2000) render(positionStore.getState(), positionStore.getState()) positionStore.subscribe(render) ``` -------------------------------- ### Create a Zustand Store with TypeScript State and Actions Source: https://zustand.docs.pmnd.rs/guides/beginner-typescript This snippet demonstrates how to define a strongly typed Zustand store using TypeScript interfaces. It shows the definition of state properties and actions, and how to create the store using `create` with a generic type parameter to enforce the state shape, ensuring type safety and compile-time validation. ```typescript // store.ts import { create } from 'zustand' // Define types for state & actions interface BearState { bears: number food: string feed: (food: string) => void } // Create store using the curried form of `create` export const useBearStore = create()((set) => ({ bears: 2, food: 'honey', feed: (food) => set(() => ({ food })), })) ``` -------------------------------- ### Zustand `combine` Middleware for State Management Source: https://zustand.docs.pmnd.rs/guides/advanced-typescript This example shows how to use Zustand's `combine` middleware to create a store. The `combine` middleware infers the state type automatically, simplifying store creation by merging an initial state object with actions defined in a callback. It trades a small amount of type-safety for convenience, as the `get` and `set` functions within the action creator might have slightly less precise types than the final store state. ```typescript import { create } from 'zustand' import { combine } from 'zustand/middleware' const useBearStore = create( combine({ bears: 0 }, (set) => ({ increase: (by: number) => set((state) => ({ bears: state.bears + by })), })), ) ``` -------------------------------- ### Basic `useStore` Hook Usage in React Source: https://zustand.docs.pmnd.rs/hooks/use-store This snippet demonstrates the fundamental syntax for using the `useStore` hook. It shows how to connect a React component to a vanilla Zustand store and optionally use a selector function to extract specific state, ensuring efficient re-renders. ```javascript const someState = useStore(store, selectorFn) ``` -------------------------------- ### Create a Zustand store with initial state and actions Source: https://zustand.docs.pmnd.rs/getting-started/introduction This JavaScript snippet demonstrates how to create a basic Zustand store using the `create` function. It defines initial state (`bears`) and actions (`increasePopulation`, `removeAllBears`, `updateBears`) that modify the state. The `set` function is used to update the store's state, either by merging objects or using a functional update. ```javascript import { create } from 'zustand' const useBear = create((set) => ({ bears: 0, increasePopulation: () => set((state) => ({ bears: state.bears + 1 })), removeAllBears: () => set({ bears: 0 }), updateBears: (newBears) => set({ newBears }) })) ``` -------------------------------- ### Expose Zustand `get` Unsoundness with Synchronous Call Source: https://zustand.docs.pmnd.rs/guides/advanced-typescript This snippet demonstrates a type unsoundness issue in Zustand where calling `get()` synchronously during store initialization results in `undefined`, despite the types promising a value of type `T`. This highlights a limitation in how Zustand's types can fully represent runtime behavior, particularly for synchronous `get` calls before state is fully established. ```typescript import { create } from 'zustand' const useBoundStore = create<{ foo: number }>()((_, get) => ({ foo: get().foo, })) ``` -------------------------------- ### Create Zustand Store for Game State Management Source: https://zustand.docs.pmnd.rs/guides/tutorial-tic-tac-toe Sets up a Zustand store using the combine middleware to manage game state including history and xIsNext. Provides setHistory and setXIsNext actions that support both direct values and updater functions, enabling flexible state updates from components. ```JavaScript import { create } from 'zustand' import { combine } from 'zustand/middleware' const useGameStore = create( combine({ history: [Array(9).fill(null)], xIsNext: true }, (set) => { return { setHistory: (nextHistory) => { set((state) => ({ history: typeof nextHistory === 'function' ? nextHistory(state.history) : nextHistory, })) }, setXIsNext: (nextXIsNext) => { set((state) => ({ xIsNext: typeof nextXIsNext === 'function' ? nextXIsNext(state.xIsNext) : nextXIsNext, })) }, } }), ) ``` -------------------------------- ### Listen to hydration start event in Zustand Source: https://zustand.docs.pmnd.rs/integrations/persisting-store-data Registers a listener callback that fires when the hydration process starts. Returns an unsubscribe function to remove the listener. Useful for tracking hydration lifecycle and triggering side effects. ```javascript const unsub = useBoundStore.persist.onHydrate((state) => { console.log('hydration starts') }) // later on... unsub() ``` -------------------------------- ### Basic `combine` middleware usage in Zustand Source: https://zustand.docs.pmnd.rs/middlewares/combine Illustrates the fundamental structure of using the `combine` middleware, showing how it merges an initial state with an additional state creator function to produce a new state creator. This pattern simplifies state management by automatically inferring types. ```javascript const nextStateCreatorFn = combine(initialState, additionalStateCreatorFn) ``` -------------------------------- ### Zustand Game Store Setup with Combine Middleware Source: https://zustand.docs.pmnd.rs/guides/tutorial-tic-tac-toe Initializes a Zustand store for tic-tac-toe game state using the combine middleware. Manages squares array (9 elements initialized to null) and xIsNext boolean flag. Provides setSquares and setXIsNext actions that support both direct values and updater functions for flexible state updates. ```JavaScript import { create } from 'zustand' import { combine } from 'zustand/middleware' const useGameStore = create( combine({ squares: Array(9).fill(null), xIsNext: true }, (set) => { return { setSquares: (nextSquares) => { set((state) => ({ squares: typeof nextSquares === 'function' ? nextSquares(state.squares) : nextSquares, })) }, setXIsNext: (nextXIsNext) => { set((state) => ({ xIsNext: typeof nextXIsNext === 'function' ? nextXIsNext(state.xIsNext) : nextXIsNext, })) }, } }), ) ``` -------------------------------- ### Basic Zustand Store Creation Source: https://zustand.docs.pmnd.rs/apis/create Demonstrates the fundamental way to create a Zustand store using the `create` function, which returns a React Hook for state management. ```javascript const useSomeStore = create(stateCreatorFn) ``` -------------------------------- ### Valid Zustand v5 `setState` Calls Source: https://zustand.docs.pmnd.rs/migrations/migrating-to-v5 This snippet provides examples of valid `setState` calls in Zustand v5, demonstrating both a partial state update (the default behavior) and a complete state replacement when the `replace` flag is explicitly set to `true`. These examples adhere to the stricter type requirements introduced in v5. ```javascript // Partial state update (valid) store.setState({ key: 'value' }) // Complete state replacement (valid) store.setState({ key: 'value' }, true) ``` -------------------------------- ### Create Per-Route Zustand Store Provider Source: https://zustand.docs.pmnd.rs/guides/nextjs Wraps the CounterStoreProvider at the page level instead of the root layout. This pattern creates an isolated store instance per route, useful when different routes need separate state management. Requires explicit provider wrapping at each route that needs the store. ```typescript import { CounterStoreProvider } from '@/providers/counter-store-provider' import { HomePage } from '@/components/pages/home-page' export default function Home() { return ( ) } ``` -------------------------------- ### Initialize Zustand Store and Subscribe to Changes Source: https://zustand.docs.pmnd.rs/apis/create-store Initializes the render function with the current store state and sets up a subscription to re-render whenever the store state changes. The render function is called immediately with the initial state, then automatically triggered on any state updates through the subscribe method. ```javascript render(personStore.getInitialState(), personStore.getInitialState()) personStore.subscribe(render) ``` -------------------------------- ### Node Server Execution Command Source: https://zustand.docs.pmnd.rs/guides/ssr-and-hydration Command to start the Express server after TypeScript compilation. Runs the compiled server.js file using Node.js runtime. ```bash node server.js ``` -------------------------------- ### Create Counter Store Provider with React Context Source: https://zustand.docs.pmnd.rs/guides/nextjs Creates a context-based provider component that initializes a Zustand store once and shares it across the component tree. Includes a custom hook for accessing the store with selector support. The provider ensures re-render safety by creating the store only once using useState. ```typescript // src/providers/counter-store-provider.tsx 'use client' import { type ReactNode, createContext, useState, useContext } from 'react' import { useStore } from 'zustand' import { type CounterStore, createCounterStore } from '@/stores/counter-store' export type CounterStoreApi = ReturnType export const CounterStoreContext = createContext( undefined, ) export interface CounterStoreProviderProps { children: ReactNode } export const CounterStoreProvider = ({ children, }: CounterStoreProviderProps) => { const [store] = useState(() => createCounterStore()) return ( {children} ) } export const useCounterStore = ( selector: (store: CounterStore) => T, ): T => { const counterStoreContext = useContext(CounterStoreContext) if (!counterStoreContext) { throw new Error(`useCounterStore must be used within CounterStoreProvider`) } return useStore(counterStoreContext, selector) } ``` -------------------------------- ### devtools(stateCreatorFn, devtoolsOptions) Source: https://zustand.docs.pmnd.rs/middlewares/devtools Integrates a Zustand store with the Redux DevTools Extension for enhanced debugging capabilities, including time-travel debugging and state inspection. This middleware requires the `@redux-devtools/extension` library to be installed. ```APIDOC ## FUNCTION devtools(stateCreatorFn, devtoolsOptions) ### Description Integrates a Zustand store with the Redux DevTools Extension, allowing for time-travel debugging and inspection of state changes. This middleware enhances the debugging experience by providing a visual interface for store actions and state. It requires the `@redux-devtools/extension` library to be installed. ### Method FUNCTION ### Endpoint N/A (Middleware Function) ### Parameters #### Path Parameters N/A #### Query Parameters N/A #### Request Body - **stateCreatorFn** (StateCreator) - Required - A function that defines the initial state and actions of your Zustand store. It takes `set`, `get`, and `store` as arguments. - **devtoolsOptions** (DevtoolsOptions) - Optional - An object to configure the Redux DevTools integration. - **name** (string) - Optional - A custom identifier for the connection in the Redux DevTools. - **enabled** (boolean) - Optional - Defaults to `true` in development, `false` in production. Controls whether the Redux DevTools integration is active. - **anonymousActionType** (string) - Optional - Defaults to inferred action type or 'anonymous'. A string to use as the action type for mutations without an explicit name. - **store** (string) - Optional - A custom identifier for the store instance within Redux DevTools. - **actionsDenylist** (string | string[]) - Optional - A string or array of strings (regex patterns) to filter out specific actions from being displayed in Redux DevTools. For example, `['secret.*']` will filter out all actions starting with "secret". ### Request Example ```javascript import { create } from 'zustand'; import { devtools } from 'zustand/middleware'; type MyStore = { count: number; increment: () => void; }; const useMyStore = create()( devtools( (set) => ({ count: 0, increment: () => set((state) => ({ count: state.count + 1 }), false, 'myStore/increment'), }), { name: 'MyZustandStore', anonymousActionType: 'unknownAction', actionsDenylist: ['internal/.*'] } ) ); // Example of debugging a Slices pattern based store: // const useJungleStore = create()( // devtools((...args) => ({ // ...createBearSlice(...args), // ...createFishSlice(...args), // })), // ); ``` ### Response #### Success Response (N/A) The `devtools` function returns a modified `StateCreator` function that can be passed to `create()` to initialize a Zustand store with DevTools integration. #### Response Example ```javascript // The return value is a modified state creator function, // which is then used by `create` to build the store. // There is no direct "response body" from calling devtools itself. ``` ``` -------------------------------- ### Initialize Zustand Vanilla Store with Custom URL Persistence in TypeScript Source: https://zustand.docs.pmnd.rs/middlewares/persist This TypeScript snippet demonstrates the creation of a vanilla Zustand store (`positionStore`) integrated with the `persist` middleware. It defines the store's state and actions, and crucially, configures the `persist` middleware to use the `searchParamsStorage` custom adapter, ensuring the store's state is saved to and loaded from the URL. ```typescript import { createStore } from 'zustand/vanilla' import { persist, createJSONStorage } from 'zustand/middleware' type PositionStoreState = { position: { x: number; y: number } } type PositionStoreActions = { setPosition: (nextPosition: PositionStoreState['position']) => void } type PositionStore = PositionStoreState & PositionStoreActions const positionStore = createStore()( persist( (set) => ({ position: { x: 0, y: 0 }, setPosition: (position) => set({ position }), }), { name: 'position-storage', storage: createJSONStorage(() => searchParamsStorage), }, ), ) ```