Skip to content
D
Documentation

Debug store updates

how-to
3 min readUpdated

Use devtools to inspect state changes in Redux DevTools without adding Redux or a reducer. Name the connection and each update so you can find the action that changed your state.

1. Set up browser debugging

In your React TypeScript project, install Zustand and the extension library:

bash
npm install zustand @redux-devtools/extension

Install the Redux DevTools browser extension too. The npm package does not replace the browser extension: the middleware connects through the extension exposed on window.

2. Name the store and its updates

Wrap the state creator with devtools inside create. devtools returns a state creator; create returns the hook your components use to select state and actions. No provider is needed.

This browser entry point mounts two controls and a bear count. Use it with an HTML element whose id is root.

tsx
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import { create } from 'zustand'
import { devtools } from 'zustand/middleware'

type BearStore = {
  bears: number
  addBears: (by: number) => void
  addOne: () => void
}

const useBearStore = create<BearStore>()(
  devtools(
    (set) => ({
      bears: 0,
      addBears: (by) =>
        set(
          (state) => ({ bears: state.bears + by }),
          undefined,
          { type: 'bear/addBears', by },
        ),
      addOne: () => set((state) => ({ bears: state.bears + 1 })),
    }),
    {
      name: 'BearStore',
      anonymousActionType: 'bear/unnamed',
      enabled: true,
    },
  ),
)

function App() {
  const bears = useBearStore((state) => state.bears)
  const addBears = useBearStore((state) => state.addBears)
  const addOne = useBearStore((state) => state.addOne)

  return (
    <main style={{ minHeight: 200 }}>
      <h1>{bears} bears</h1>
      <button onClick={() => addBears(2)}>Add two bears</button>
      <button onClick={addOne}>Add one bear</button>
    </main>
  )
}

const container = document.getElementById('root')!
createRoot(container).render(
  <StrictMode>
    <App />
  </StrictMode>,
)
The initial bear count and two buttons let you trigger the updates to inspect in DevTools.

Pass the action label as the third argument to set. A string supplies the action type; an object supplies type and payload fields. Keep the second argument undefined to preserve the default replacement logic.

3. Inspect the result

Open Redux DevTools and select the BearStore connection. Click Add two bears: the page shows 2 bears, and DevTools records bear/addBears with the payload field by: 2 and the updated bears state. Click Add one bear next: the page shows 3 bears, and DevTools records bear/unnamed because that update has no explicit action label.

You can also jump to an earlier state in DevTools. The middleware applies that state to the store, so the selected bear count on the page changes with it.

Options that matter

Pass these options as the second argument to devtools.

OptionTypeDefaultWhat it does
namestringNot suppliedNames the DevTools connection. Use different names to separate connections.
storestringNot suppliedIdentifies a store within a shared named connection. Its state appears under this key, and its action types get a store/ prefix.
anonymousActionTypestringInferred caller name, or 'anonymous' if unavailableSupplies the label for updates without an explicit action type. A nonempty value takes precedence over inference.
enabledbooleanEnabled outside production mode; disabled in production modeEnables or disables the integration for this store.

The sample sets enabled: true explicitly, so it attempts to connect even in production. For a production build that must not connect, set enabled: false. Omit the option to use the middleware's mode-based default. Disabling the integration does not disable state updates or your React controls.

To group multiple stores, give each the same name and a distinct store identifier. Without store, each middleware instance opens its own connection.

Pitfalls

  • If no connection appears, check that the browser extension is available and that enabled is not false. Without the extension, the store still works, but no debugging connection is created.
  • DevTools displays one connection at a time. Use its store selector to choose another connection rather than assuming the other store is missing.
  • Use explicit third-argument labels when you need stable action names. Updates without them use anonymousActionType, caller-name inference, or the 'anonymous' fallback.
  • For middleware composition and slice typing, follow Type stores and middleware.

Try the live Zustand counter demo for the hook-and-action interaction. The sample above adds named DevTools updates to that pattern.

Was this page helpful?

Debug store updates — zustand · GPT-6.1 Sol