Skip to main content
Zustand provides two primary ways to create stores: create() for React applications and createStore() for vanilla JavaScript/TypeScript.

Creating React Stores with create()

The create() function creates a React Hook that manages state and provides API utilities.

Type Signature

type Create = {
  <T, Mos extends [StoreMutatorIdentifier, unknown][] = []>(
    initializer: StateCreator<T, [], Mos>,
  ): UseBoundStore<Mutate<StoreApi<T>, Mos>>
}

Basic Usage

1

Import create

Import the create function from Zustand.
import { create } from 'zustand'
2

Define your state creator

The state creator function receives three arguments:
  • set: Function to update state
  • get: Function to read current state
  • store: The store API object
type 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 }),
}))
3

Use the hook in components

The returned hook can be used directly in React components.
function BearCounter() {
  const bears = useBearStore((state) => state.bears)
  return <h1>{bears} bears around here...</h1>
}

Understanding the State Creator Function

The state creator is the heart of your store. It defines the initial state and actions.
const useCountStore = create<{ count: number }>((set) => ({
  count: 0,
}))

The set Function

The set function is how you update state in Zustand. It accepts two arguments:
partial
T | Partial<T> | (state: T) => T | Partial<T>
The new state or a function that returns the new state
replace
boolean
default:"false"
Whether to replace the entire state instead of merging
By default, set performs a shallow merge:
set({ count: 1 }) // Merges { count: 1 } with existing state

The get Function

The get function returns the current state:
const useStore = create<{ count: number; double: () => number }>((set, get) => ({
  count: 5,
  double: () => get().count * 2,
}))
The get function is useful for actions that need to read the current state without causing re-renders.

Creating Vanilla Stores with createStore()

The createStore() function creates a vanilla store that can be used outside of React.

Type Signature

type CreateStore = {
  <T, Mos extends [StoreMutatorIdentifier, unknown][] = []>(
    initializer: StateCreator<T, [], Mos>,
  ): Mutate<StoreApi<T>, Mos>
}

Basic Usage

import { createStore } from 'zustand/vanilla'

type CounterState = {
  count: number
  increment: () => void
}

const counterStore = createStore<CounterState>()((set) => ({
  count: 0,
  increment: () => set((state) => ({ count: state.count + 1 })),
}))

// Access state directly
counterStore.getState().count // 0

// Call actions
counterStore.getState().increment()

// Subscribe to changes
const unsubscribe = counterStore.subscribe((state, prevState) => {
  console.log('count changed from', prevState.count, 'to', state.count)
})

StoreApi Interface

Both create() and createStore() return a store that implements the StoreApi interface:
interface StoreApi<T> {
  setState: SetStateInternal<T>
  getState: () => T
  getInitialState: () => T
  subscribe: (listener: (state: T, prevState: T) => void) => () => void
}
The main difference between create() and createStore() is that create() returns a React Hook with the StoreApi attached, while createStore() returns just the StoreApi.

TypeScript Support

Zustand has excellent TypeScript support. You can define your state types explicitly:
type State = {
  count: number
  text: string
}

type Actions = {
  increment: () => void
  setText: (text: string) => void
}

type Store = State & Actions

const useStore = create<Store>()((set) => ({
  count: 0,
  text: '',
  increment: () => set((state) => ({ count: state.count + 1 })),
  setText: (text) => set({ text }),
}))
When using TypeScript, make sure to use the curried version create<T>()((set) => ...) to get proper type inference.

Common Patterns

Separating State and Actions

type State = {
  firstName: string
  lastName: string
}

type Actions = {
  updateFirstName: (firstName: State['firstName']) => void
  updateLastName: (lastName: State['lastName']) => void
}

const usePersonStore = create<State & Actions>((set) => ({
  firstName: '',
  lastName: '',
  updateFirstName: (firstName) => set({ firstName }),
  updateLastName: (lastName) => set({ lastName }),
}))

Using Primitives as State

const useCount = create<number>(() => 0)

// Update with replace flag
useCount.setState((count) => count + 1, true)
When your state is a primitive value, always use the replace flag set to true when calling setState.

Next Steps

Reading State

Learn how to read and select state in components

Updating State

Master state updates and immutable patterns

Build docs developers (and LLMs) love