https://github.com/sahadev/zustand-state-monitor
A React state monitor for Zustand stores with automatic registration and debugging capabilities
https://github.com/sahadev/zustand-state-monitor
zustand-state-management
Last synced: 3 days ago
JSON representation
A React state monitor for Zustand stores with automatic registration and debugging capabilities
- Host: GitHub
- URL: https://github.com/sahadev/zustand-state-monitor
- Owner: sahadev
- Created: 2025-09-18T09:05:21.000Z (19 days ago)
- Default Branch: master
- Last Pushed: 2025-09-19T11:48:34.000Z (18 days ago)
- Last Synced: 2025-09-19T13:32:15.029Z (18 days ago)
- Topics: zustand-state-management
- Language: TypeScript
- Homepage: https://zustand-state-monitor.surge.sh/
- Size: 83 KB
- Stars: 0
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# zustand-state-monitor
A React state monitor for Zustand stores with automatic registration and debugging capabilities.
## 🚀 [Live Demo](https://zustand-state-monitor.surge.sh/)
Try out the interactive demo to see Zustand State Monitor in action!
## Features
- 🔍 **Monitor Zustand State Changes**: Track all state changes with detailed history
- 🔄 **Automatic Registration**: Auto-register Zustand stores with minimal setup
- 🎣 **React Hooks**: Easy-to-use hooks for React integration
- 📊 **Dev Tools**: Built-in visual debugging interface
- 🎯 **Selective Monitoring**: Monitor specific stores or filter by criteria
- 📝 **Type Safe**: Full TypeScript support
- 🚀 **Zero Dependencies**: No additional dependencies beyond React and Zustand## Installation
```bash
npm install zustand-state-monitor
# or
yarn add zustand-state-monitor
```## Quick Start
### Basic Usage
```tsx
import { create } from 'zustand';
import { useStateMonitor, registerExistingStore } from 'zustand-state-monitor';// Create your Zustand store
const useCountStore = create((set) => ({
count: 0,
increment: () => set((state) => ({ count: state.count + 1 })),
decrement: () => set((state) => ({ count: state.count - 1 })),
}));// Register the store for monitoring
registerExistingStore('countStore', useCountStore);function App() {
const monitor = useStateMonitor();
// Your component logic here
returnYour App;
}
```### Auto Registration
```tsx
import { create } from 'zustand';
import { withAutoRegister } from 'zustand-state-monitor';// Automatically register store on creation
const useCountStore = withAutoRegister('countStore', () =>
create((set) => ({
count: 0,
increment: () => set((state) => ({ count: state.count + 1 })),
}))
);
```### Using Hooks
```tsx
import { useStateHistory, useStateListener } from 'zustand-state-monitor';function DebugComponent() {
// Get state change history
const { history, clearHistory } = useStateHistory('countStore');
// Listen to state changes
useStateListener((change) => {
console.log('State changed:', change);
}, ['countStore']);return (
State History ({history.length})
Clear History
{/* Render history */}
);
}
```### Dev Tools
```tsx
import { StateMonitorDevTools } from 'zustand-state-monitor';function App() {
return (
{/* Your app content */}
);
}
```## API Reference
### Core Classes
#### StateMonitor
The main monitoring class that tracks state changes.
```tsx
import { StateMonitor } from 'zustand-state-monitor';const monitor = new StateMonitor({
enabled: true,
maxHistorySize: 100,
debugMode: false,
logChanges: true
});
```### Hooks
#### useStateMonitor()
Get access to the global state monitor instance.
```tsx
const monitor = useStateMonitor();
```#### useStateHistory(storeName?)
Get state change history for a specific store or all stores.
```tsx
const { history, clearHistory } = useStateHistory('myStore');
```#### useStateListener(callback, storeNames?)
Listen to state changes across stores.
```tsx
useStateListener((change) => {
console.log('State changed:', change);
}, ['store1', 'store2']);
```#### useStoreRegistration(storeName, store, autoRegister?)
Manage store registration with automatic cleanup.
```tsx
const { isRegistered, register, unregister } = useStoreRegistration(
'myStore',
myStore,
true // auto register
);
```### Auto Registration
#### registerExistingStore(storeName, store, config?)
Register an existing Zustand store.
```tsx
registerExistingStore('myStore', myZustandStore);
```#### withAutoRegister(storeName, createStore, config?)
Wrap store creation with automatic registration.
```tsx
const useMyStore = withAutoRegister('myStore', () =>
create((set) => ({ /* store config */ }))
);
```#### setupGlobalAutoRegister(config?)
Set up global auto-registration for all Zustand stores (experimental).
```tsx
setupGlobalAutoRegister({
debugMode: true,
exclude: ['temporaryStore']
});
```### Configuration
```tsx
interface StateMonitorConfig {
enabled?: boolean; // Enable/disable monitoring
maxHistorySize?: number; // Maximum history entries per store
debugMode?: boolean; // Enable debug logging
autoRegister?: boolean; // Auto-register new stores
logChanges?: boolean; // Log changes to console
filters?: {
storeNames?: string[]; // Only monitor specific stores
excludeKeys?: string[]; // Exclude specific state keys
};
}
```### State Change Object
```tsx
interface StateChange {
storeName: string; // Name of the store
oldState: T; // Previous state
newState: T; // New state
timestamp: number; // Change timestamp
diff?: Partial; // State differences
}
```## Examples
### Complete Example
```tsx
import React from 'react';
import { create } from 'zustand';
import {
registerExistingStore,
useStateMonitor,
useStateHistory,
StateMonitorDevTools
} from 'zustand-state-monitor';// Create stores
const useCountStore = create((set) => ({
count: 0,
increment: () => set((state) => ({ count: state.count + 1 })),
decrement: () => set((state) => ({ count: state.count - 1 })),
}));const useUserStore = create((set) => ({
user: null,
setUser: (user) => set({ user }),
logout: () => set({ user: null }),
}));// Register stores
registerExistingStore('counter', useCountStore);
registerExistingStore('user', useUserStore);function Counter() {
const { count, increment, decrement } = useCountStore();
const { history } = useStateHistory('counter');
return (
Counter: {count}
+
-
Changes: {history.length}
);
}function App() {
const monitor = useStateMonitor();
return (
State Monitor Demo
Monitor Status
Registered stores: {monitor.getRegisteredStores().join(', ')}
Total changes: {monitor.getHistory().length}
{/* Dev Tools */}
);
}export default App;
```## Best Practices
1. **Register stores early**: Register your stores as early as possible in your app lifecycle
2. **Use meaningful names**: Give your stores descriptive names for easier debugging
3. **Limit history size**: Set appropriate `maxHistorySize` to prevent memory issues
4. **Development only**: Consider disabling in production or use feature flags
5. **Cleanup**: The hooks handle cleanup automatically, but manual registration should be paired with unregistration## TypeScript Support
Full TypeScript support with proper type inference:
```tsx
interface CountState {
count: number;
increment: () => void;
}const useCountStore = create((set) => ({
count: 0,
increment: () => set((state) => ({ count: state.count + 1 })),
}));// Type-safe registration
registerExistingStore('counter', useCountStore);// Type-safe history
const { history } = useStateHistory('counter');
```## License
MIT