Connect a Zustand store to Redux DevTools and inspect its named state updates.
Use this when you want a development timeline of store updates without adopting Redux. Wrap the store's state creator in devtools, then create the hook with create. Install the Redux DevTools package and the browser extension before running the example:
bashnpm install zustand @redux-devtools/extension
Install the Redux DevTools browser extension as well.
Add the middleware to a React store
For the basic store and component-binding pattern, see Create and bind a React store. The difference here is the devtools wrapper and the third set argument: this complete App.tsx example renders an article status, and each button records a distinct action type in Redux DevTools.
tsximport { createRoot } from 'react-dom/client'
import { create } from 'zustand'
import { devtools } from 'zustand/middleware'
type ArticleStore = {
status: 'draft' | 'published'
publish: () => void
reopen: () => void
}
const useArticleStore = create<ArticleStore>()(
devtools((set) => ({
status: 'draft',
publish: () => set({ status: 'published' }, undefined, 'article/publish'),
reopen: () => set({ status: 'draft' }, undefined, 'article/reopen'),
})),
)
function ArticleStatus() {
const status = useArticleStore((state) => state.status)
const publish = useArticleStore((state) => state.publish)
const reopen = useArticleStore((state) => state.reopen)
return (
<main>
<p>Article status: {status}</p>
<button onClick={publish}>Publish</button>
<button onClick={reopen}>Reopen</button>
</main>
)
}
const container = document.getElementById('root')!
createRoot(container).render(<ArticleStatus />)
Open Redux DevTools and select the store to inspect its state and updates. Clicking Publish changes the rendered status to published and records article/publish; clicking Reopen changes it back to draft and records article/reopen. You can inspect either update or use DevTools time travel.
Options to identify the connection
Pass the optional second argument to devtools when you need a distinct connection name or want to control whether the integration runs.
| Option | Type | Default | What it does |
|---|---|---|---|
name | string | Not specified | Sets a custom identifier for the Redux DevTools connection. |
enabled | boolean | true in development; false in production | Enables or disables the Redux DevTools integration for this store. |
anonymousActionType | string | Inferred action type, or anonymous if unavailable | Sets the action type used for mutations without a supplied action name. |
store | string | Not specified | Sets a custom identifier for this store in Redux DevTools. |
For example, add { name: 'CounterStore' } as the second argument to devtools to label the connection. Give updates meaningful action types in set as in the example; without a supplied name, DevTools uses an inferred action type when available and otherwise falls back to anonymous.
Pitfalls
devtoolsrequires the@redux-devtools/extensionpackage as well as the browser extension. In production, the integration is disabled by default; setenabledonly when you intentionally want a different setting.- Redux DevTools displays one store at a time by default. Use its store selector to switch to another store.
- An update without an explicit action type can appear as
anonymouswhen Zustand cannot infer a name. Add a thirdsetargument, such as'counter/increment', to make its timeline entry explicit.
Live demo
Try the Zustand live demo to see Zustand running in the browser.
Was this page helpful?