Skip to content

Commit b25a144

Browse files
committed
docs: Revise README for clarity and enhance feature descriptions
1 parent 81a752e commit b25a144

1 file changed

Lines changed: 137 additions & 31 deletions

File tree

README.md

Lines changed: 137 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
# EasyAppDev.Blazor.Store
1+
# EasyAppDev.Blazor.Store - Blazor State Management Library
22

3-
**Type-safe state management for Blazor using C# records.**
3+
**Zustand-inspired state management for Blazor** - Type-safe, immutable, zero-boilerplate state management using C# records. The simplest way to manage state in Blazor Server, WebAssembly, and Auto modes.
44

5-
*Inspired by Zustand • Built for C# developers*
5+
*Built for C# developers who want Redux-like power without the complexity*
66

77
[![NuGet](https://img.shields.io/nuget/v/EasyAppDev.Blazor.Store.svg)](https://www.nuget.org/packages/EasyAppDev.Blazor.Store/)
88
[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
@@ -28,25 +28,43 @@
2828

2929
---
3030

31-
## What is State Management?
31+
## Features at a Glance
32+
33+
| Feature | Description |
34+
|---------|-------------|
35+
| **Immutable State** | C# records with `with` expressions for predictable state updates |
36+
| **Zero Boilerplate** | No actions, reducers, or dispatchers required |
37+
| **Redux DevTools** | Time-travel debugging with full state inspection |
38+
| **Persistence** | Automatic LocalStorage/SessionStorage state saving |
39+
| **Cross-Tab Sync** | Real-time state synchronization across browser tabs |
40+
| **Server Sync** | SignalR-based real-time collaboration with presence |
41+
| **Undo/Redo** | Full history stack with memory management |
42+
| **Type-Safe** | Complete IntelliSense and compile-time checking |
43+
| **Async Support** | Built-in debounce, throttle, and lazy loading |
44+
| **Optimistic Updates** | Instant UI feedback with automatic rollback |
45+
46+
---
47+
48+
## What is State Management in Blazor?
3249

3350
In Blazor applications, "state" is any data your app needs to remember—user input, fetched data, UI flags like "is loading" or "is sidebar open." Without a state management library, you end up passing data through component parameters, juggling `EventCallback` chains, or scattering state across services. This quickly becomes hard to track and debug. A state management library gives you a single source of truth: one place where state lives, one way to update it, and automatic notifications to any component that cares. Think of it as a central database for your UI that keeps everything in sync.
3451

3552
---
3653

37-
## Why This Library?
54+
## Why Choose This Blazor State Management Library?
3855

3956
No actions. No reducers. No dispatchers. Just C# records with pure methods.
4057

4158
```csharp
42-
// Define state as a record with transformation methods
59+
// Define Blazor state as an immutable C# record
4360
public record CounterState(int Count)
4461
{
62+
// Pure state transformation - returns new immutable state
4563
public CounterState Increment() => this with { Count = Count + 1 };
4664
public CounterState Decrement() => this with { Count = Count - 1 };
4765
}
4866

49-
// Use in components
67+
// Use in Blazor components with automatic state subscription
5068
@inherits StoreComponent<CounterState>
5169

5270
<h1>@State.Count</h1>
@@ -63,7 +81,7 @@ public record CounterState(int Count)
6381

6482
---
6583

66-
## Quick Start
84+
## Quick Start - Blazor State Management Setup
6785

6886
### 1. Install
6987

@@ -74,7 +92,7 @@ dotnet add package EasyAppDev.Blazor.Store
7492
### 2. Register
7593

7694
```csharp
77-
// Program.cs
95+
// Program.cs - Register Blazor state store with dependency injection
7896
builder.Services.AddStoreWithUtilities(
7997
new CounterState(0),
8098
(store, sp) => store.WithDefaults(sp, "Counter"));
@@ -84,41 +102,45 @@ builder.Services.AddStoreWithUtilities(
84102

85103
```razor
86104
@page "/counter"
105+
@* Inherit from StoreComponent for automatic state subscription *@
87106
@inherits StoreComponent<CounterState>
88107
89108
<h1>@State.Count</h1>
90109
<button @onclick="@(() => UpdateAsync(s => s.Increment()))">+</button>
91110
<button @onclick="@(() => UpdateAsync(s => s.Decrement()))">-</button>
92111
```
93112

94-
That's it. State updates automatically propagate to all subscribed components.
113+
That's it. State updates automatically propagate to all subscribed Blazor components.
95114

96115
---
97116

98117
## Table of Contents
99118

100-
1. [Core Concepts](#core-concepts)
101-
2. [Registration Options](#registration-options)
102-
3. [Async Helpers](#async-helpers)
103-
4. [Optimistic Updates](#optimistic-updates)
104-
5. [Undo/Redo History](#undoredo-history)
105-
6. [Query System](#query-system)
106-
7. [Cross-Tab Sync](#cross-tab-sync)
107-
8. [Server Sync (SignalR)](#server-sync-signalr)
108-
9. [Immer-Style Updates](#immer-style-updates)
109-
10. [Redux-Style Actions](#redux-style-actions)
110-
11. [Plugin System](#plugin-system)
111-
12. [Security](#security)
112-
13. [Selectors & Performance](#selectors--performance)
113-
14. [Persistence & DevTools](#persistence--devtools)
114-
15. [Middleware](#middleware)
115-
16. [Blazor Render Modes](#blazor-render-modes)
116-
17. [API Reference](#api-reference)
117-
18. [Breaking Changes in v2.0.0](#breaking-changes-in-v200)
119+
1. [Features at a Glance](#features-at-a-glance)
120+
2. [Core Concepts](#core-concepts---immutable-state-with-c-records)
121+
3. [Registration Options](#registration-options)
122+
4. [Async Helpers](#async-helpers)
123+
5. [Optimistic Updates](#optimistic-updates)
124+
6. [Undo/Redo History](#undoredo-history)
125+
7. [Query System](#query-system)
126+
8. [Cross-Tab Sync](#cross-tab-sync)
127+
9. [Server Sync (SignalR)](#server-sync-signalr)
128+
10. [Immer-Style Updates](#immer-style-updates)
129+
11. [Redux-Style Actions](#redux-style-actions)
130+
12. [Plugin System](#plugin-system)
131+
13. [Security](#security)
132+
14. [Selectors & Performance](#selectors--performance-optimization)
133+
15. [Persistence & DevTools](#state-persistence--redux-devtools-integration)
134+
16. [Middleware](#middleware)
135+
17. [Blazor Render Modes](#blazor-render-modes)
136+
18. [API Reference](#api-reference)
137+
19. [Breaking Changes in v2.0.0](#breaking-changes-in-v200)
138+
20. [Comparison with Alternatives](#comparison-with-other-blazor-state-management-libraries)
139+
21. [FAQ](#frequently-asked-questions-faq)
118140

119141
---
120142

121-
## Core Concepts
143+
## Core Concepts - Immutable State with C# Records
122144

123145
### State = Immutable Record
124146

@@ -879,7 +901,7 @@ Use `TransformOnSave` to exclude sensitive fields from localStorage:
879901

880902
---
881903

882-
## Selectors & Performance
904+
## Selectors & Performance Optimization
883905

884906
### The Problem
885907

@@ -926,7 +948,7 @@ protected override ImmutableList<Todo> SelectState(TodoState s) =>
926948

927949
---
928950

929-
## Persistence & DevTools
951+
## State Persistence & Redux DevTools Integration
930952

931953
### LocalStorage Persistence
932954

@@ -1169,6 +1191,82 @@ public override Task OnAfterUpdateAsync(AppState previousState, AppState newStat
11691191

11701192
---
11711193

1194+
## Comparison with Other Blazor State Management Libraries
1195+
1196+
| Feature | EasyAppDev.Blazor.Store | Fluxor | Blazor-State | Morris.Moxy |
1197+
|---------|------------------------|--------|--------------|-------------|
1198+
| **Learning Curve** | Minimal - just C# records | Steep - Redux patterns | Moderate - MediatR patterns | Moderate |
1199+
| **Boilerplate** | Zero - no actions/reducers | High - actions, reducers, effects | Medium - handlers required | Low |
1200+
| **DevTools** | Redux DevTools | Redux DevTools | None | None |
1201+
| **Persistence** | Built-in | Manual | Manual | Manual |
1202+
| **Cross-Tab Sync** | Built-in | Manual | None | None |
1203+
| **Server Sync** | Built-in SignalR | Manual | None | None |
1204+
| **Undo/Redo** | Built-in | Manual | None | None |
1205+
| **Type Safety** | Full | Full | Full | Full |
1206+
| **Bundle Size** | ~50KB | ~100KB | ~30KB | ~20KB |
1207+
1208+
### When to Choose This Library
1209+
1210+
- **Choose EasyAppDev.Blazor.Store** if you want minimal boilerplate, built-in features (persistence, sync, undo/redo), and a Zustand-like developer experience
1211+
- **Choose Fluxor** if your team is familiar with Redux/Flux patterns and needs strict unidirectional data flow
1212+
- **Choose Blazor-State** if you prefer MediatR-style request/handler patterns
1213+
1214+
---
1215+
1216+
## Frequently Asked Questions (FAQ)
1217+
1218+
### How does this compare to Fluxor?
1219+
1220+
Fluxor follows traditional Redux patterns with actions, reducers, and effects. EasyAppDev.Blazor.Store takes a simpler approach inspired by Zustand - your state is just a C# record with methods. No boilerplate, no ceremony. Both support Redux DevTools.
1221+
1222+
### Can I use this with Blazor Server?
1223+
1224+
Yes. Use `AddScopedStore` for full feature support (DevTools, persistence, cross-tab sync) in Blazor Server. Singleton stores work but cannot use JavaScript-dependent features.
1225+
1226+
### How do I persist state to localStorage?
1227+
1228+
```csharp
1229+
builder.Services.AddStoreWithUtilities(
1230+
new AppState(),
1231+
(store, sp) => store
1232+
.WithDefaults(sp, "App")
1233+
.WithPersistence(sp, "app-state")); // Auto-saves to localStorage
1234+
```
1235+
1236+
### Does this work with .NET MAUI Blazor?
1237+
1238+
Yes. The core store functionality works in MAUI Blazor Hybrid apps. Browser-specific features (DevTools, localStorage, cross-tab sync) require a browser context.
1239+
1240+
### How do I handle async operations like API calls?
1241+
1242+
Use the built-in `ExecuteAsync` helper or async state methods:
1243+
1244+
```csharp
1245+
await ExecuteAsync(
1246+
() => api.LoadUsersAsync(),
1247+
loading: s => s with { IsLoading = true },
1248+
success: (s, users) => s with { Users = users, IsLoading = false },
1249+
error: (s, ex) => s with { Error = ex.Message, IsLoading = false });
1250+
```
1251+
1252+
### Is state shared across browser tabs?
1253+
1254+
Not by default. Enable cross-tab synchronization with `WithTabSync`:
1255+
1256+
```csharp
1257+
.WithTabSync(sp, opts => opts.Channel("my-app").EnableMessageSigning())
1258+
```
1259+
1260+
### How do I debug state changes?
1261+
1262+
Install the [Redux DevTools browser extension](https://github.com/reduxjs/redux-devtools). State changes are automatically logged in DEBUG builds when using `WithDefaults()` or `WithDevTools()`.
1263+
1264+
### Can multiple components share the same state?
1265+
1266+
Yes. All components inheriting `StoreComponent<T>` for the same state type automatically share state and receive updates.
1267+
1268+
---
1269+
11721270
## Common Gotchas
11731271

11741272
1. **Always use `with`**: `state with { X = 1 }` not `state.X = 1`
@@ -1199,4 +1297,12 @@ MIT © EasyAppDev
11991297

12001298
**[GitHub](https://github.com/mashrulhaque/EasyAppDev.Blazor.Store)****[Issues](https://github.com/mashrulhaque/EasyAppDev.Blazor.Store/issues)****[Discussions](https://github.com/mashrulhaque/EasyAppDev.Blazor.Store/discussions)**
12011299

1300+
---
1301+
1302+
### Found this library helpful?
1303+
1304+
If EasyAppDev.Blazor.Store has made state management easier in your Blazor projects, consider giving it a ⭐ on GitHub. It helps others discover the library and motivates continued development.
1305+
1306+
[![GitHub stars](https://img.shields.io/github/stars/mashrulhaque/EasyAppDev.Blazor.Store?style=social)](https://github.com/mashrulhaque/EasyAppDev.Blazor.Store)
1307+
12021308
</div>

0 commit comments

Comments
 (0)