@@ -23,8 +23,10 @@ Inspired by Zustand • Built for C# • Designed for Developer Joy
2323- ⚡ ** Blazing-fast performance** - Granular updates with selectors for 25x fewer re-renders in high-frequency scenarios
2424- 🎨 ** Smart optimizations** - Memoization, batch updates, and lazy loading built right in
2525- 🧰 ** Powerful DevTools** - Time-travel debugging with Redux DevTools integration
26+ - 📊 ** Built-in Diagnostics** - Real-time monitoring of state changes, renders, and performance metrics (DEBUG mode)
2627- 🚀 ** Async-first** - First-class support for async operations without extra ceremony
2728- 📦 ** Tiny API surface** - Learn the entire API in minutes, not days
29+ - 🎁 ** Simplified API** - One-liner setup with ` WithDefaults() ` for common configurations
2830
2931** If you've used Zustand in React, you'll feel right at home. If you haven't, you'll wonder why state management was ever complicated.**
3032
@@ -50,6 +52,7 @@ Inspired by Zustand • Built for C# • Designed for Developer Joy
5052 - [ Async Operations] ( #async-operations )
5153 - [ Persistence] ( #persistence )
5254 - [ DevTools] ( #devtools )
55+ - [ Diagnostics & Monitoring] ( #diagnostics--monitoring ) 🆕
5356 - [ Middleware] ( #middleware )
5457- [ API Reference] ( #api-reference )
5558- [ Best Practices] ( #best-practices )
@@ -98,11 +101,22 @@ public record CounterState(int Count, string? LastAction = null)
98101In your ` Program.cs ` :
99102
100103``` csharp
104+ // Simple - with default setup (DevTools + Logging)
101105builder .Services .AddStore (
102- new CounterState (0 ), // Initial state
103- store => store .WithDevTools (" Counter" )); // Optional: Enable DevTools
106+ new CounterState (0 ),
107+ (store , sp ) => store .WithDefaults (sp , " Counter" ));
108+
109+ // Or manual configuration
110+ builder .Services .AddStore (
111+ new CounterState (0 ),
112+ (store , sp ) => store
113+ .WithJSRuntime (sp .GetRequiredService <IJSRuntime >())
114+ .WithDevTools (" Counter" )
115+ .WithLogging ());
104116```
105117
118+ > 💡 ** New in this version** : Use ` WithDefaults() ` for one-liner setup with JSRuntime, DevTools, and Logging!
119+
106120### Step 3: Use in Components
107121
108122``` razor
@@ -1184,20 +1198,30 @@ async Task LoadUsers()
11841198Automatically save and restore state:
11851199
11861200``` csharp
1201+ // NEW: Simplified API
11871202builder .Services .AddStore (
11881203 new AppState (),
1189- store => store .WithPersistence (
1190- PersistenceType .LocalStorage , // or SessionStorage
1191- " app-state" , // storage key
1192- debounceMs : 500 // optional: debounce saves
1193- ));
1204+ (store , sp ) => store
1205+ .WithDefaults (sp , " MyApp" )
1206+ .WithPersistence (sp , " app-state" )); // Auto-creates LocalStorageProvider
1207+
1208+ // Or with manual provider configuration
1209+ builder .Services .AddStore (
1210+ new AppState (),
1211+ (store , sp ) => {
1212+ var jsRuntime = sp .GetRequiredService <IJSRuntime >();
1213+ var localStorage = new LocalStorageProvider (jsRuntime );
1214+ return store .WithPersistence (localStorage , " app-state" );
1215+ });
11941216```
11951217
11961218State is automatically:
11971219- Saved to storage on every update (debounced)
11981220- Restored when the app loads
11991221- Serialized/deserialized with System.Text.Json
12001222
1223+ > 💡 ** New** : The simplified ` WithPersistence(sp, key) ` method automatically creates a LocalStorageProvider for you!
1224+
12011225### DevTools
12021226
12031227Time-travel debugging with Redux DevTools:
@@ -1217,6 +1241,101 @@ builder.Services.AddStore(
12171241
12181242** Install:** [ Redux DevTools Extension] ( https://github.com/reduxjs/redux-devtools )
12191243
1244+ ---
1245+
1246+ ### Diagnostics & Monitoring
1247+
1248+ > 🆕 ** New Feature** : Real-time diagnostics panel for monitoring state changes, component renders, and performance.
1249+
1250+ ** Built-in diagnostics system** (available only in DEBUG builds) provides deep visibility into your application's state management:
1251+
1252+ #### Setup
1253+
1254+ ``` csharp
1255+ // In Program.cs
1256+ builder .Services .AddStoreDiagnostics (); // Register diagnostics service
1257+
1258+ builder .Services .AddStore (
1259+ new CounterState (0 ),
1260+ (store , sp ) => store
1261+ .WithDefaults (sp , " Counter" )
1262+ .WithDiagnosticsIfAvailable (sp )); // Safely adds diagnostics if available
1263+ ```
1264+
1265+ #### Features
1266+
1267+ The diagnostics system tracks:
1268+
1269+ - ** 📜 Action History** - Every state update with:
1270+ - Action names and timestamps
1271+ - Before/after state snapshots
1272+ - State diffs showing what changed
1273+ - Update duration timings
1274+
1275+ - ** 📊 Performance Metrics** - Real-time performance data:
1276+ - Average, min, and max update times
1277+ - Total update count
1278+ - P95/P99 percentiles
1279+
1280+ - ** 🎨 Render Tracking** - Component render monitoring:
1281+ - Which components rendered and when
1282+ - Render frequency per component
1283+ - Render counts for optimization insights
1284+
1285+ - ** 🔌 Subscription Monitoring** - Track all subscriptions:
1286+ - Active subscriptions count
1287+ - Component lifecycle tracking
1288+ - Subscription creation/disposal events
1289+
1290+ #### Usage
1291+
1292+ Add the ` DiagnosticPanel ` component to any page:
1293+
1294+ ``` razor
1295+ @page "/diagnostics"
1296+
1297+ <h1>Store Diagnostics</h1>
1298+
1299+ #if DEBUG
1300+ <DiagnosticPanel DisplayMode="DiagnosticDisplayMode.Inline" InitiallyCollapsed="false" />
1301+ #else
1302+ <p>Diagnostics only available in DEBUG builds</p>
1303+ #endif
1304+ ```
1305+
1306+ ** Display modes:**
1307+ - ` Inline ` - Full-width panel embedded in page
1308+ - ` Floating ` - Draggable overlay (default)
1309+
1310+ ** Example diagnostic output:**
1311+
1312+ ```
1313+ 📊 Performance Metrics
1314+ Store: Counter
1315+ ├─ Total Updates: 47
1316+ ├─ Avg Duration: 0.8ms
1317+ ├─ Min Duration: 0.3ms
1318+ ├─ Max Duration: 2.1ms
1319+ └─ P95 Duration: 1.5ms
1320+
1321+ 📜 Recent Actions
1322+ 1. INCREMENT (0.5ms ago)
1323+ Counter: 5 → 6
1324+ 2. INCREMENT (1.2s ago)
1325+ Counter: 4 → 5
1326+ 3. RESET (5.3s ago)
1327+ Counter: 15 → 0
1328+
1329+ 🎨 Component Renders
1330+ ├─ Counter.razor: 8 renders
1331+ ├─ CounterDisplay.razor: 8 renders
1332+ └─ CounterStats.razor: 3 renders
1333+ ```
1334+
1335+ > ⚠️ ** Note** : Diagnostics are compiled out in Release builds to ensure zero performance overhead in production.
1336+
1337+ ---
1338+
12201339### Middleware
12211340
12221341Intercept state updates for cross-cutting concerns:
@@ -1251,6 +1370,7 @@ builder.Services.AddStore(
12511370- ` DevToolsMiddleware ` - Redux DevTools integration
12521371- ` PersistenceMiddleware ` - LocalStorage/SessionStorage sync
12531372- ` LoggingMiddleware ` - State change logging
1373+ - ` DiagnosticsMiddleware ` - Performance monitoring and diagnostics (DEBUG only)
12541374
12551375---
12561376
@@ -1298,19 +1418,37 @@ public interface IStore<TState>
12981418### Registration
12991419
13001420``` csharp
1301- // Simple
1421+ // Simple - no configuration
13021422services .AddStore (new MyState ());
13031423
1304- // With configuration
1424+ // With defaults (recommended)
13051425services .AddStore (
13061426 new MyState (),
1307- store => store
1427+ (store , sp ) => store .WithDefaults (sp , " MyStore" ));
1428+
1429+ // Full configuration
1430+ services .AddStore (
1431+ new MyState (),
1432+ (store , sp ) => store
1433+ .WithDefaults (sp , " StoreName" )
1434+ .WithPersistence (sp , " storage-key" )
1435+ .WithDiagnosticsIfAvailable (sp )
1436+ .WithMiddleware <MyMiddleware >()
1437+ );
1438+
1439+ // Manual configuration (for advanced scenarios)
1440+ services .AddStore (
1441+ new MyState (),
1442+ (store , sp ) => store
1443+ .WithJSRuntime (sp .GetRequiredService <IJSRuntime >())
13081444 .WithDevTools (" StoreName" )
1309- .WithPersistence ( PersistenceType . LocalStorage , " key " )
1445+ .WithLogging ( )
13101446 .WithMiddleware <MyMiddleware >()
13111447);
13121448```
13131449
1450+ > 💡 ** Tip** : The new ` (store, sp) => ` pattern gives you access to the service provider for dependency injection within store configuration.
1451+
13141452---
13151453
13161454## Best Practices
@@ -1629,6 +1767,30 @@ Explore comprehensive documentation:
16291767
16301768---
16311769
1770+ ## What's New
1771+
1772+ ### Recent Updates
1773+
1774+ ** 🆕 Diagnostics & Monitoring System**
1775+ - Built-in diagnostics panel for monitoring state changes, renders, and performance
1776+ - Real-time action history with state diffs
1777+ - Performance metrics tracking (update timings, P95/P99)
1778+ - Component render tracking and subscription monitoring
1779+ - Zero performance overhead (DEBUG-only compilation)
1780+
1781+ ** 🎁 Simplified API**
1782+ - ` WithDefaults(sp, name) ` - One-liner for common setup
1783+ - ` WithPersistence(sp, key) ` - Simplified persistence without manual provider creation
1784+ - ` WithDiagnosticsIfAvailable(sp) ` - Safe diagnostics addition
1785+ - New ` (store, sp) => ` registration pattern for dependency injection
1786+
1787+ ** 📦 Enhanced Store Registration**
1788+ - Service provider access in configuration
1789+ - Cleaner, more composable builder pattern
1790+ - Better support for dependency injection
1791+
1792+ ---
1793+
16321794## Contributing
16331795
16341796We welcome contributions! This library is designed to stay simple and focused.
0 commit comments