@buoy-gg/zustand
v2.1.10
Published
Zustand store DevTools for React Native
Readme
@buoy-gg/zustand
Zustand store DevTools for React Native. Live state change monitoring, state inspection, and diff visualization for your Zustand stores.
Setup
npm install @buoy-gg/zustandOne line — zero store modifications
import { watchStores } from '@buoy-gg/zustand';
import { useCounterStore } from './stores/counter';
import { useAuthStore } from './stores/auth';
import { useCartStore } from './stores/cart';
// Call once at module scope (e.g. in _layout.tsx or App.tsx):
watchStores({
counterStore: useCounterStore,
authStore: useAuthStore,
cartStore: useCartStore,
});That's it. The Zustand tool appears automatically in FloatingDevTools.
Your stores stay completely untouched — watchStores uses Zustand's built-in .subscribe() to observe changes from the outside. It never modifies setState or any store internals.
Safe by design
- Add in seconds — one import, one function call
- Remove in seconds — delete those two lines, done
- Cannot break your stores — all listener code is wrapped in try/catch. Even if our code has a bug, your stores keep working normally
- No monkey-patching — we call
.subscribe(), the same API your own components use
Cleanup (optional)
const cleanup = watchStores({ ... });
// Later, to stop watching:
cleanup();Advanced: middleware mode
If you want extra detail (the exact partial passed to setState and precise timing), you can opt into the middleware approach per-store:
import { create } from 'zustand';
import { buoyDevTools } from '@buoy-gg/zustand';
const useCounterStore = create(
buoyDevTools(
(set) => ({
count: 0,
increment: () => set((s) => ({ count: s.count + 1 })),
}),
{ name: 'counterStore' }
)
);This wraps setState internally, so it captures what was passed and how long it took. Works with middleware chaining (persist, immer, etc.):
import { persist } from 'zustand/middleware';
const useAuthStore = create(
buoyDevTools(
persist(
(set) => ({ user: null, login: (u) => set({ user: u }) }),
{ name: 'auth-storage' }
),
{ name: 'authStore' }
)
);Features
- Live state change capture — every state update is recorded with prev/next state
- State inspection — full JSON viewer for state after each change
- State diffing — tree view and split view comparing previous vs. next state
- Changed keys tracking — see exactly which top-level keys changed per update
- Store color coding — each store gets a consistent color for easy visual tracking
- Performance monitoring — updates slower than 16ms are flagged (middleware mode)
- Persist awareness — auto-detects stores using Zustand's persist middleware
- Search & filter — search by store name or changed keys, filter to only state-changing updates
- Jump to state — restore any store to a previously captured state
- Reset store — reset any store to its initial state
- Copy to clipboard — copy state data (Pro)
Comparison
| | watchStores() | buoyDevTools() middleware |
|---|---|---|
| Setup | One line, no store changes | Wrap each store's create() |
| Risk | Zero — uses subscribe only | Low — wraps setState |
| Captures partial | No | Yes |
| Captures timing | No | Yes |
| State diff | Yes | Yes |
| Changed keys | Yes | Yes |
| Persist detection | Yes | Yes |
Exports
// Primary — non-intrusive
import { watchStores } from '@buoy-gg/zustand';
// Advanced — middleware
import { buoyDevTools } from '@buoy-gg/zustand';
// Preset
import { zustandToolPreset, createZustandTool } from '@buoy-gg/zustand';
// Hook
import { useZustandStateChanges } from '@buoy-gg/zustand';
// Components (for custom UIs)
import {
ZustandModal,
ZustandStateChangeItem,
ZustandStateDetailContent,
ZustandIcon,
} from '@buoy-gg/zustand';
// Types
import type {
ZustandStateChange,
ZustandStoreInfo,
ZustandFilter,
StateChangeCategory,
} from '@buoy-gg/zustand';