react-hooks-global-states 16.0.5 โ 16.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +169 -133
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -1,24 +1,30 @@
|
|
|
1
1
|
# react-hooks-global-states ๐
|
|
2
2
|
|
|
3
|
+
<div align="center">
|
|
4
|
+
|
|
3
5
|

|
|
4
6
|
|
|
7
|
+
</div>
|
|
8
|
+
|
|
5
9
|
<div align="center">
|
|
6
10
|
|
|
7
|
-
**Shared
|
|
11
|
+
**Shared state that feels like `useState`.**
|
|
8
12
|
|
|
9
|
-
|
|
13
|
+
Share state across your React application with the familiar `useState` API, subscribe to only the slice a component needs, and grow into typed actions, chainable selectors, and scoped stores. This is the shared core of the family, without a platform persistence layer. Inspect every store, action, and state change in the DevTools panel, or from your terminal.
|
|
10
14
|
|
|
11
15
|
[](https://www.npmjs.com/package/react-hooks-global-states)
|
|
12
16
|
[](https://www.npmjs.com/package/react-hooks-global-states)
|
|
13
|
-
[](https://github.com/johnny-quesada-developer/react-
|
|
17
|
+
[](https://github.com/johnny-quesada-developer/react-global-state-hooks/blob/master/LICENSE)
|
|
18
|
+
|
|
19
|
+
[**Website**](https://johnny-quesada-developer.github.io/react-global-state-hooks/) ยท [**Documentation**](https://johnny-quesada-developer.github.io/react-global-state-hooks/docs/) ยท [**Examples**](https://johnny-quesada-developer.github.io/react-global-state-hooks/examples/) ยท [**DevTools**](https://johnny-quesada-developer.github.io/react-global-state-hooks/docs/devtools/) ยท [**Agentic DevTools**](https://johnny-quesada-developer.github.io/react-global-state-hooks/agentic-devtools/)
|
|
14
20
|
|
|
15
|
-
[
|
|
21
|
+
Created by [Johnny Quesada](https://johnny-quesada-developer.github.io/react-global-state-hooks/about/), author of the React Global State Hooks family.
|
|
16
22
|
|
|
17
23
|
</div>
|
|
18
24
|
|
|
19
25
|
---
|
|
20
26
|
|
|
21
|
-
##
|
|
27
|
+
## Start with a single hook
|
|
22
28
|
|
|
23
29
|
```tsx
|
|
24
30
|
import { createGlobalState } from 'react-hooks-global-states';
|
|
@@ -26,7 +32,7 @@ import { createGlobalState } from 'react-hooks-global-states';
|
|
|
26
32
|
export const useCounter = createGlobalState(0);
|
|
27
33
|
```
|
|
28
34
|
|
|
29
|
-
|
|
35
|
+
A shared store, ready to use. Global hooks work without a provider; use `createContext` when a subtree needs its own instance.
|
|
30
36
|
|
|
31
37
|
```tsx
|
|
32
38
|
// Use it anywhere, instantly
|
|
@@ -38,51 +44,42 @@ function Counter() {
|
|
|
38
44
|
|
|
39
45
|
---
|
|
40
46
|
|
|
41
|
-
##
|
|
47
|
+
## Built for React applications
|
|
42
48
|
|
|
43
|
-
|
|
44
|
-
<tr>
|
|
45
|
-
<td width="50%">
|
|
49
|
+
### **Familiar React API**
|
|
46
50
|
|
|
47
|
-
|
|
51
|
+
If you know `useState`, you already know the API.
|
|
48
52
|
|
|
49
53
|
```tsx
|
|
50
|
-
//
|
|
51
|
-
const [
|
|
54
|
+
// Local state
|
|
55
|
+
const [count, setCount] = useState(0);
|
|
52
56
|
|
|
53
|
-
//
|
|
54
|
-
const [
|
|
57
|
+
// Shared state
|
|
58
|
+
const [count, setCount] = useCounter();
|
|
55
59
|
```
|
|
56
60
|
|
|
57
|
-
|
|
58
|
-
<td width="50%">
|
|
61
|
+
### **Precise Subscriptions**
|
|
59
62
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
Subscribe to a slice so unrelated store changes do not trigger component updates.
|
|
63
|
+
Subscribe to a slice, so unrelated store changes do not re-render your component.
|
|
63
64
|
|
|
64
65
|
```tsx
|
|
65
66
|
// Only re-renders when name changes
|
|
66
|
-
const [name] = useStore((
|
|
67
|
+
const [name] = useStore((state) => state.user.name);
|
|
67
68
|
```
|
|
68
69
|
|
|
69
|
-
|
|
70
|
-
</tr>
|
|
71
|
-
|
|
72
|
-
<tr>
|
|
73
|
-
<td width="50%">
|
|
70
|
+
### **Chainable Selectors**
|
|
74
71
|
|
|
75
|
-
|
|
72
|
+
Build reusable state hooks on top of other selector hooks.
|
|
76
73
|
|
|
77
74
|
```tsx
|
|
78
|
-
const useUsers = useStore.createSelectorHook((
|
|
79
|
-
|
|
75
|
+
const useUsers = useStore.createSelectorHook((state) => state.users);
|
|
76
|
+
|
|
77
|
+
const useAdmins = useUsers.createSelectorHook((users) => users.filter((user) => user.isAdmin));
|
|
80
78
|
```
|
|
81
79
|
|
|
82
|
-
|
|
83
|
-
<td width="50%">
|
|
80
|
+
### **Actions (Optional)**
|
|
84
81
|
|
|
85
|
-
|
|
82
|
+
Keep mutation logic next to the store when a feature needs more structure.
|
|
86
83
|
|
|
87
84
|
```tsx
|
|
88
85
|
const useAuth = createGlobalState(null, {
|
|
@@ -90,6 +87,7 @@ const useAuth = createGlobalState(null, {
|
|
|
90
87
|
login(credentials) {
|
|
91
88
|
return async ({ setState }) => {
|
|
92
89
|
const user = await api.login(credentials);
|
|
90
|
+
|
|
93
91
|
setState(user);
|
|
94
92
|
};
|
|
95
93
|
},
|
|
@@ -97,13 +95,9 @@ const useAuth = createGlobalState(null, {
|
|
|
97
95
|
});
|
|
98
96
|
```
|
|
99
97
|
|
|
100
|
-
|
|
101
|
-
</tr>
|
|
98
|
+
### **Context Mode**
|
|
102
99
|
|
|
103
|
-
|
|
104
|
-
<td width="50%">
|
|
105
|
-
|
|
106
|
-
### ๐ช **Context Mode**
|
|
100
|
+
Need an isolated instance instead of app-wide state? Same state model, inside a provider.
|
|
107
101
|
|
|
108
102
|
```tsx
|
|
109
103
|
const Form = createContext({ name: '', email: '' });
|
|
@@ -113,26 +107,53 @@ const Form = createContext({ name: '', email: '' });
|
|
|
113
107
|
</Form.Provider>;
|
|
114
108
|
```
|
|
115
109
|
|
|
116
|
-
|
|
117
|
-
|
|
110
|
+
### **Persistence, When Your Platform Has It**
|
|
111
|
+
|
|
112
|
+
This package is the state model without a storage layer. Add `react-global-state-hooks` for `localStorage`, or `react-native-global-state-hooks` for async storage. The store API is the same in all three.
|
|
113
|
+
|
|
114
|
+
```tsx
|
|
115
|
+
// Same store, one extra option in the platform packages
|
|
116
|
+
const useSettings = createGlobalState({ theme: 'dark' });
|
|
117
|
+
```
|
|
118
118
|
|
|
119
|
-
###
|
|
119
|
+
### **Non-Reactive API**
|
|
120
120
|
|
|
121
|
-
|
|
121
|
+
Read, update, or subscribe to state outside React components.
|
|
122
122
|
|
|
123
123
|
```tsx
|
|
124
|
-
// In API interceptors, WebSockets, utils...
|
|
125
124
|
const token = useAuth.getState().token;
|
|
126
|
-
|
|
125
|
+
|
|
126
|
+
useAuth.setState({ user: nextUser });
|
|
127
127
|
```
|
|
128
128
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
129
|
+
---
|
|
130
|
+
|
|
131
|
+
## Agentic DevTools
|
|
132
|
+
|
|
133
|
+
Give your coding agent the runtime, not a guess. With the [Chrome extension](https://chromewebstore.google.com/detail/bafojplmkpejhglhjpibpdhoblickpee) open on your app, the `rgsh` command that ships with this package reads store state, runs store actions and prints exactly which paths changed โ from the terminal your agent already uses.
|
|
134
|
+
|
|
135
|
+
```bash
|
|
136
|
+
npm install --save-dev ws # rgsh talks to the extension over a local WebSocket
|
|
137
|
+
npx rgsh --list # every store DevTools knows about, with its actions
|
|
138
|
+
npx rgsh action todos add "Write the docs" # run an action; prints each changed path, before โ after
|
|
139
|
+
npx rgsh state todos todos[0].done # read the result back
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
Import the debug entry first in your **development** entry file, before any module that creates a store, and keep it out of production builds:
|
|
143
|
+
|
|
144
|
+
```ts
|
|
145
|
+
import 'react-hooks-global-states/debug';
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
`rgsh` works on state and actions only; it does not click or type in the page. Take the [Agentic DevTools tour](https://johnny-quesada-developer.github.io/react-global-state-hooks/agentic-devtools/) for the inspect โ act โ verify workflow, and read the [DevTools guide](https://johnny-quesada-developer.github.io/react-global-state-hooks/docs/devtools/) for setup, the panel and the exit codes.
|
|
149
|
+
|
|
150
|
+
| The app being inspected | Stores, actions, and state diffs in the panel |
|
|
151
|
+
| ------------------------- | ----------------------------------------------- |
|
|
152
|
+
| <img alt="Debug playground app" src="https://johnny-quesada-developer.github.io/react-global-state-hooks/devtools/showcase/app.png" width="380"> | <img alt="DevTools panel" src="https://johnny-quesada-developer.github.io/react-global-state-hooks/devtools/showcase/panel.png" width="620"> |
|
|
132
153
|
|
|
133
154
|
---
|
|
134
155
|
|
|
135
|
-
##
|
|
156
|
+
## Installation
|
|
136
157
|
|
|
137
158
|
```bash
|
|
138
159
|
npm install react-hooks-global-states
|
|
@@ -145,9 +166,9 @@ npm install react-hooks-global-states
|
|
|
145
166
|
|
|
146
167
|
---
|
|
147
168
|
|
|
148
|
-
##
|
|
169
|
+
## Quick Start
|
|
149
170
|
|
|
150
|
-
###
|
|
171
|
+
### Your first shared store
|
|
151
172
|
|
|
152
173
|
```tsx
|
|
153
174
|
import { createGlobalState } from 'react-hooks-global-states';
|
|
@@ -220,13 +241,13 @@ function LoginButton({ authenticate }: { authenticate: () => Promise<User> }) {
|
|
|
220
241
|
|
|
221
242
|
---
|
|
222
243
|
|
|
223
|
-
##
|
|
244
|
+
## Core Features Deep Dive
|
|
224
245
|
|
|
225
|
-
###
|
|
246
|
+
### Global State with `createGlobalState`
|
|
226
247
|
|
|
227
|
-
|
|
248
|
+
Keep app-wide state outside the component tree and subscribe wherever it is needed.
|
|
228
249
|
|
|
229
|
-
####
|
|
250
|
+
#### The Basics
|
|
230
251
|
|
|
231
252
|
```tsx
|
|
232
253
|
// Primitives
|
|
@@ -249,7 +270,7 @@ const useExpensiveState = createGlobalState(() => {
|
|
|
249
270
|
});
|
|
250
271
|
```
|
|
251
272
|
|
|
252
|
-
####
|
|
273
|
+
#### Focused subscriptions with Selectors
|
|
253
274
|
|
|
254
275
|
Selectors keep components subscribed to the state they use.
|
|
255
276
|
|
|
@@ -298,7 +319,7 @@ function NotificationCount() {
|
|
|
298
319
|
| `useStore()` | Any store value change |
|
|
299
320
|
| `useStore(selector)` | A change to the selected value |
|
|
300
321
|
|
|
301
|
-
####
|
|
322
|
+
#### Computed Values with Dependencies
|
|
302
323
|
|
|
303
324
|
Derive values from both store state and component-local values, with explicit dependencies.
|
|
304
325
|
|
|
@@ -376,7 +397,7 @@ function AdvancedFiltered() {
|
|
|
376
397
|
}
|
|
377
398
|
```
|
|
378
399
|
|
|
379
|
-
####
|
|
400
|
+
#### Reusable Selector Hooks
|
|
380
401
|
|
|
381
402
|
Compose reusable selector hooks. Each hook returns its selected value directly.
|
|
382
403
|
|
|
@@ -441,7 +462,7 @@ function ActivateAll() {
|
|
|
441
462
|
}
|
|
442
463
|
```
|
|
443
464
|
|
|
444
|
-
**
|
|
465
|
+
**Selector composition:**
|
|
445
466
|
|
|
446
467
|
| Feature | Benefit |
|
|
447
468
|
| -------------------- | ------------------------------------------ |
|
|
@@ -451,9 +472,9 @@ function ActivateAll() {
|
|
|
451
472
|
| ๐จ **Clean Code** | No repetitive selector logic in components |
|
|
452
473
|
| โก **Performance** | Automatic memoization and change detection |
|
|
453
474
|
|
|
454
|
-
####
|
|
475
|
+
#### Actions - When You Need Structure
|
|
455
476
|
|
|
456
|
-
|
|
477
|
+
Add actions to give your store a clear, reusable mutation API.
|
|
457
478
|
|
|
458
479
|
```tsx
|
|
459
480
|
const useStore = createGlobalState(
|
|
@@ -544,15 +565,15 @@ function TodoApp() {
|
|
|
544
565
|
);
|
|
545
566
|
}
|
|
546
567
|
|
|
547
|
-
//
|
|
568
|
+
// Direct updates remain available through setState.
|
|
548
569
|
const handleQuickFix = () => {
|
|
549
570
|
useStore.setState((s) => ({ ...s, filter: 'all' }));
|
|
550
571
|
};
|
|
551
572
|
```
|
|
552
573
|
|
|
553
|
-
####
|
|
574
|
+
#### Store access outside React
|
|
554
575
|
|
|
555
|
-
|
|
576
|
+
Use the same store API in components, services, and background workflows.
|
|
556
577
|
|
|
557
578
|
```tsx
|
|
558
579
|
const useAuth = createGlobalState({ user: null, token: null });
|
|
@@ -594,9 +615,9 @@ const unsubscribe = useAuth.subscribe(
|
|
|
594
615
|
);
|
|
595
616
|
```
|
|
596
617
|
|
|
597
|
-
####
|
|
618
|
+
#### Observable Fragments
|
|
598
619
|
|
|
599
|
-
Create observable slices
|
|
620
|
+
Create observable state slices for subscriptions outside React.
|
|
600
621
|
|
|
601
622
|
```tsx
|
|
602
623
|
const useStore = createGlobalState({
|
|
@@ -622,7 +643,7 @@ console.log(countObservable.getState()); // Current count value
|
|
|
622
643
|
const doubledObservable = countObservable.createObservable((count) => count * 2);
|
|
623
644
|
```
|
|
624
645
|
|
|
625
|
-
####
|
|
646
|
+
#### Metadata - Non-Reactive Side Info
|
|
626
647
|
|
|
627
648
|
Keep request counters and timestamps in metadata when they are read only by handlers or background work.
|
|
628
649
|
Put loading indicators and displayed errors in state so components subscribe to their changes.
|
|
@@ -646,11 +667,11 @@ function recordFetchedItems(items: string[]) {
|
|
|
646
667
|
|
|
647
668
|
---
|
|
648
669
|
|
|
649
|
-
###
|
|
670
|
+
### Scoped State with `createContext`
|
|
650
671
|
|
|
651
|
-
|
|
672
|
+
Use `createContext` to give each provider its own store instance.
|
|
652
673
|
|
|
653
|
-
####
|
|
674
|
+
#### The Basics
|
|
654
675
|
|
|
655
676
|
```tsx
|
|
656
677
|
import { createContext } from 'react-hooks-global-states';
|
|
@@ -692,7 +713,7 @@ function FormPreview() {
|
|
|
692
713
|
}
|
|
693
714
|
```
|
|
694
715
|
|
|
695
|
-
####
|
|
716
|
+
#### Provider Variations
|
|
696
717
|
|
|
697
718
|
```tsx
|
|
698
719
|
const ThemeContext = createContext('light');
|
|
@@ -719,7 +740,7 @@ function App() {
|
|
|
719
740
|
}
|
|
720
741
|
```
|
|
721
742
|
|
|
722
|
-
####
|
|
743
|
+
#### Context selectors
|
|
723
744
|
|
|
724
745
|
Use the same selectors, actions and metadata with state scoped to each provider.
|
|
725
746
|
|
|
@@ -748,7 +769,7 @@ function EmailField() {
|
|
|
748
769
|
}
|
|
749
770
|
```
|
|
750
771
|
|
|
751
|
-
####
|
|
772
|
+
#### Context with Actions
|
|
752
773
|
|
|
753
774
|
```tsx
|
|
754
775
|
const CounterContext = createContext(0, {
|
|
@@ -791,9 +812,9 @@ function App() {
|
|
|
791
812
|
}
|
|
792
813
|
```
|
|
793
814
|
|
|
794
|
-
####
|
|
815
|
+
#### Reusable Context Selectors
|
|
795
816
|
|
|
796
|
-
|
|
817
|
+
Compose reusable selectors for scoped stores with the same API.
|
|
797
818
|
|
|
798
819
|
```tsx
|
|
799
820
|
const DataContext = createContext({
|
|
@@ -832,9 +853,9 @@ function UserList() {
|
|
|
832
853
|
}
|
|
833
854
|
```
|
|
834
855
|
|
|
835
|
-
####
|
|
856
|
+
#### Testing context stores
|
|
836
857
|
|
|
837
|
-
|
|
858
|
+
Access the context store directly to inspect changes, inject test data, and exercise updates.
|
|
838
859
|
|
|
839
860
|
```tsx
|
|
840
861
|
import { renderHook } from '@testing-library/react';
|
|
@@ -860,9 +881,9 @@ describe('CounterContext', () => {
|
|
|
860
881
|
});
|
|
861
882
|
```
|
|
862
883
|
|
|
863
|
-
####
|
|
884
|
+
#### Lifecycle Hooks
|
|
864
885
|
|
|
865
|
-
|
|
886
|
+
Connect initialization and cleanup to the context lifecycle.
|
|
866
887
|
|
|
867
888
|
```tsx
|
|
868
889
|
const DataContext = createContext([], {
|
|
@@ -906,11 +927,11 @@ function App() {
|
|
|
906
927
|
|
|
907
928
|
---
|
|
908
929
|
|
|
909
|
-
###
|
|
930
|
+
### External Actions with `actions`
|
|
910
931
|
|
|
911
|
-
|
|
932
|
+
Define actions in focused modules and bind them to an existing store.
|
|
912
933
|
|
|
913
|
-
####
|
|
934
|
+
#### Direct Binding
|
|
914
935
|
|
|
915
936
|
```tsx
|
|
916
937
|
import { createGlobalState, actions } from 'react-hooks-global-states';
|
|
@@ -944,9 +965,9 @@ counterActions.double(); // count = 10
|
|
|
944
965
|
counterActions.decrement(3); // count = 7
|
|
945
966
|
```
|
|
946
967
|
|
|
947
|
-
####
|
|
968
|
+
#### Action templates
|
|
948
969
|
|
|
949
|
-
|
|
970
|
+
Define action templates before the store API is available, then bind them in a context or lifecycle callback.
|
|
950
971
|
|
|
951
972
|
```tsx
|
|
952
973
|
import { actions, InferAPI, createContext } from 'react-hooks-global-states';
|
|
@@ -997,9 +1018,9 @@ const { loadData } = SessionContext.use.actions();
|
|
|
997
1018
|
console.log(loadData); // undefined
|
|
998
1019
|
```
|
|
999
1020
|
|
|
1000
|
-
####
|
|
1021
|
+
#### Actions Calling Actions
|
|
1001
1022
|
|
|
1002
|
-
|
|
1023
|
+
Compose actions into larger workflows.
|
|
1003
1024
|
|
|
1004
1025
|
```tsx
|
|
1005
1026
|
const useStore = createGlobalState({ count: 0, history: [] }, {
|
|
@@ -1046,9 +1067,9 @@ const storeActions = actions(useStore, {
|
|
|
1046
1067
|
storeActions.incrementTwice(5);
|
|
1047
1068
|
```
|
|
1048
1069
|
|
|
1049
|
-
####
|
|
1070
|
+
#### Access Store Actions
|
|
1050
1071
|
|
|
1051
|
-
External actions can call each other with `this` and access the store's public actions
|
|
1072
|
+
External actions can call each other with `this` and access the store's public actions.
|
|
1052
1073
|
|
|
1053
1074
|
```tsx
|
|
1054
1075
|
const useStore = createGlobalState(
|
|
@@ -1087,7 +1108,7 @@ const extraActions = actions(useStore, {
|
|
|
1087
1108
|
extraActions.incrementAndLog(5);
|
|
1088
1109
|
```
|
|
1089
1110
|
|
|
1090
|
-
####
|
|
1111
|
+
#### Actions in context stores
|
|
1091
1112
|
|
|
1092
1113
|
```tsx
|
|
1093
1114
|
import { actions, InferAPI } from 'react-hooks-global-states';
|
|
@@ -1136,11 +1157,11 @@ function Counter() {
|
|
|
1136
1157
|
|
|
1137
1158
|
---
|
|
1138
1159
|
|
|
1139
|
-
##
|
|
1160
|
+
## Advanced Patterns
|
|
1140
1161
|
|
|
1141
|
-
###
|
|
1162
|
+
### Production Architecture (File Organization)
|
|
1142
1163
|
|
|
1143
|
-
|
|
1164
|
+
Keep each domain easy to navigate with dedicated modules for its store, actions, selector hooks, and observables:
|
|
1144
1165
|
|
|
1145
1166
|
**File Structure:**
|
|
1146
1167
|
|
|
@@ -1326,9 +1347,9 @@ function TodoApp() {
|
|
|
1326
1347
|
- โ
**Namespace pattern** - Everything bundled: `todos$.useActiveTodos()`, `todos$.activeTodos$`
|
|
1327
1348
|
- โ
**Scalable** - Easy to find, test, and maintain individual pieces
|
|
1328
1349
|
|
|
1329
|
-
###
|
|
1350
|
+
### Smart Subscriptions
|
|
1330
1351
|
|
|
1331
|
-
Subscribe to
|
|
1352
|
+
Subscribe to the state slice your integration needs.
|
|
1332
1353
|
|
|
1333
1354
|
```tsx
|
|
1334
1355
|
const useStore = createGlobalState({
|
|
@@ -1362,11 +1383,11 @@ unsubRole();
|
|
|
1362
1383
|
|
|
1363
1384
|
---
|
|
1364
1385
|
|
|
1365
|
-
##
|
|
1386
|
+
## `uniqueId` - Type-Safe Unique IDs
|
|
1366
1387
|
|
|
1367
|
-
Generate
|
|
1388
|
+
Generate unique identifiers with branded types that distinguish one domain from another.
|
|
1368
1389
|
|
|
1369
|
-
###
|
|
1390
|
+
### Basic Usage
|
|
1370
1391
|
|
|
1371
1392
|
```tsx
|
|
1372
1393
|
import { uniqueId } from 'react-hooks-global-states';
|
|
@@ -1377,9 +1398,9 @@ const id2 = uniqueId('user:'); // "user:a1b2c3d4-e5f6-7890-abcd-ef1234567890"
|
|
|
1377
1398
|
const id3 = uniqueId('session:'); // "session:a1b2c3d4-e5f6-7890-abcd-ef1234567890"
|
|
1378
1399
|
```
|
|
1379
1400
|
|
|
1380
|
-
###
|
|
1401
|
+
### Branded identifiers
|
|
1381
1402
|
|
|
1382
|
-
Create ID generators with compile-time type checking
|
|
1403
|
+
Create ID generators with compile-time type checking.
|
|
1383
1404
|
|
|
1384
1405
|
```tsx
|
|
1385
1406
|
// Create branded generators
|
|
@@ -1396,7 +1417,7 @@ const postId: PostId = generatePostId(); // โ
"post:a1b2c3d4-e5f6-7890-abcd-ef
|
|
|
1396
1417
|
const wrong: UserId = generatePostId(); // โ Type error!
|
|
1397
1418
|
```
|
|
1398
1419
|
|
|
1399
|
-
###
|
|
1420
|
+
### Runtime Validation
|
|
1400
1421
|
|
|
1401
1422
|
```tsx
|
|
1402
1423
|
const generateUserId = uniqueId.for('user:');
|
|
@@ -1416,9 +1437,9 @@ generateUserId.assert('user:a1b2c3d4-e5f6-7890-abcd-ef1234567890'); // โ
OK
|
|
|
1416
1437
|
generateUserId.assert('post:a1b2c3d4-e5f6-7890-abcd-ef1234567890'); // โ Throws error!
|
|
1417
1438
|
```
|
|
1418
1439
|
|
|
1419
|
-
###
|
|
1440
|
+
### Strict Branding
|
|
1420
1441
|
|
|
1421
|
-
|
|
1442
|
+
Use symbol branding to distinguish identifier types even when their prefixes match.
|
|
1422
1443
|
|
|
1423
1444
|
```tsx
|
|
1424
1445
|
declare const UserBrand: unique symbol;
|
|
@@ -1437,7 +1458,7 @@ const id1: UserId = generateUserId(); // โ
|
|
|
1437
1458
|
const id2: UserId = generateUserId2(); // โ Different brands!
|
|
1438
1459
|
```
|
|
1439
1460
|
|
|
1440
|
-
###
|
|
1461
|
+
### Real-World Example
|
|
1441
1462
|
|
|
1442
1463
|
```tsx
|
|
1443
1464
|
import { createGlobalState, uniqueId } from 'react-hooks-global-states';
|
|
@@ -1519,44 +1540,50 @@ actions.addTodo('Build feature', userId);
|
|
|
1519
1540
|
|
|
1520
1541
|
---
|
|
1521
1542
|
|
|
1522
|
-
##
|
|
1543
|
+
## Documentation and examples
|
|
1544
|
+
|
|
1545
|
+
The [React Global State Hooks website](https://johnny-quesada-developer.github.io/react-global-state-hooks/) is the home for current documentation,
|
|
1546
|
+
interactive examples, and the DevTools walkthrough.
|
|
1523
1547
|
|
|
1524
|
-
|
|
|
1525
|
-
|
|
|
1526
|
-
|
|
|
1527
|
-
|
|
|
1528
|
-
|
|
|
1529
|
-
|
|
|
1548
|
+
| Explore | What you will find |
|
|
1549
|
+
| --- | --- |
|
|
1550
|
+
| [Getting started](https://johnny-quesada-developer.github.io/react-global-state-hooks/docs/getting-started/) | Create your first store and connect it to your UI. |
|
|
1551
|
+
| [API and guides](https://johnny-quesada-developer.github.io/react-global-state-hooks/docs/) | Selectors, actions, scoped state, persistence, and TypeScript. |
|
|
1552
|
+
| [Interactive examples](https://johnny-quesada-developer.github.io/react-global-state-hooks/examples/) | Explore the state model in working browser examples. |
|
|
1553
|
+
| [DevTools](https://johnny-quesada-developer.github.io/react-global-state-hooks/docs/devtools/) | Inspect state, follow actions, and use the terminal workflow. |
|
|
1554
|
+
| [Agentic DevTools](https://johnny-quesada-developer.github.io/react-global-state-hooks/agentic-devtools/) | Inspect state, run an action and read back the result from a terminal or a coding agent. |
|
|
1555
|
+
| [Platform guide](https://johnny-quesada-developer.github.io/react-global-state-hooks/docs/platform-and-versions/) | Choose the package and persistence model for your app. |
|
|
1530
1556
|
|
|
1531
1557
|
---
|
|
1532
1558
|
|
|
1533
|
-
##
|
|
1559
|
+
## Choose your package
|
|
1534
1560
|
|
|
1535
|
-
|
|
1536
|
-
| -------------------------------------------------------------------------------------------------- | -------------------- | ------------------------ |
|
|
1537
|
-
| [`react-hooks-global-states`](https://www.npmjs.com/package/react-hooks-global-states) | React / React Native | Core library |
|
|
1538
|
-
| [`react-global-state-hooks`](https://www.npmjs.com/package/react-global-state-hooks) | Web | localStorage integration |
|
|
1539
|
-
| [`react-native-global-state-hooks`](https://www.npmjs.com/package/react-native-global-state-hooks) | React Native | AsyncStorage integration |
|
|
1561
|
+
The family shares a common state API, with persistence tailored to each platform.
|
|
1540
1562
|
|
|
1541
|
-
|
|
1563
|
+
| Package | Best fit |
|
|
1564
|
+
| --- | --- |
|
|
1565
|
+
| [`react-global-state-hooks`](https://www.npmjs.com/package/react-global-state-hooks) | React web applications with optional localStorage persistence. |
|
|
1566
|
+
| [`react-native-global-state-hooks`](https://www.npmjs.com/package/react-native-global-state-hooks) | React Native applications with optional asynchronous persistence. |
|
|
1567
|
+
| [`react-hooks-global-states`](https://www.npmjs.com/package/react-hooks-global-states) | The shared core without platform-specific persistence. |
|
|
1568
|
+
| [`react-hooks-global-states-debug`](https://www.npmjs.com/package/react-hooks-global-states-debug) | Development instrumentation for the DevTools extension. |
|
|
1542
1569
|
|
|
1543
|
-
|
|
1570
|
+
See the [platform guide](https://johnny-quesada-developer.github.io/react-global-state-hooks/docs/platform-and-versions/) for package differences
|
|
1571
|
+
and the [DevTools guide](https://johnny-quesada-developer.github.io/react-global-state-hooks/docs/devtools/) for debug entry points.
|
|
1572
|
+
|
|
1573
|
+
---
|
|
1544
1574
|
|
|
1545
|
-
|
|
1575
|
+
## Built to grow with your application
|
|
1546
1576
|
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
| โ
Global + Context | โ Either/or choice |
|
|
1554
|
-
| โ
Actions (optional) | โ Required structure |
|
|
1555
|
-
| โ
Familiar hook syntax | โ New component APIs |
|
|
1577
|
+
- **Familiar from the first hook.** Share state through a `useState`-style API.
|
|
1578
|
+
- **Focused subscriptions.** Select the values a component needs.
|
|
1579
|
+
- **Composable structure.** Bring in actions, selectors, and scoped stores as your features grow.
|
|
1580
|
+
- **Persistence when your platform has it.** Add the web or React Native package for a storage layer.
|
|
1581
|
+
- **A connected debugging workflow.** Follow state and actions with the [DevTools integration](https://johnny-quesada-developer.github.io/react-global-state-hooks/docs/devtools/).
|
|
1582
|
+
- **Runtime evidence for coding agents.** Let an agent inspect, act and verify against the running app with [Agentic DevTools](https://johnny-quesada-developer.github.io/react-global-state-hooks/agentic-devtools/).
|
|
1556
1583
|
|
|
1557
1584
|
---
|
|
1558
1585
|
|
|
1559
|
-
##
|
|
1586
|
+
## Get Started Now
|
|
1560
1587
|
|
|
1561
1588
|
```bash
|
|
1562
1589
|
npm install react-hooks-global-states
|
|
@@ -1575,14 +1602,23 @@ function App() {
|
|
|
1575
1602
|
}
|
|
1576
1603
|
```
|
|
1577
1604
|
|
|
1578
|
-
|
|
1605
|
+
Continue with the [guides and interactive examples](https://johnny-quesada-developer.github.io/react-global-state-hooks/) to build your next store.
|
|
1579
1606
|
|
|
1580
1607
|
---
|
|
1581
1608
|
|
|
1582
|
-
|
|
1609
|
+
## Built by Johnny Quesada
|
|
1583
1610
|
|
|
1584
|
-
|
|
1611
|
+
Explore the [project website](https://johnny-quesada-developer.github.io/react-global-state-hooks/), meet [Johnny](https://johnny-quesada-developer.github.io/react-global-state-hooks/about/),
|
|
1612
|
+
and help shape what comes next. If the library helps your work, a GitHub star or a
|
|
1613
|
+
shared example helps more developers discover it.
|
|
1585
1614
|
|
|
1586
|
-
|
|
1615
|
+
[Star on GitHub](https://github.com/johnny-quesada-developer/react-global-state-hooks) ยท [Report an issue](https://github.com/johnny-quesada-developer/react-global-state-hooks/issues) ยท [Explore the source](https://github.com/johnny-quesada-developer/react-global-state-hooks/tree/master/libs/universal)
|
|
1587
1616
|
|
|
1588
|
-
|
|
1617
|
+
## Legacy resources
|
|
1618
|
+
|
|
1619
|
+
Earlier demos and walkthroughs are preserved here for reference. For current APIs,
|
|
1620
|
+
examples, and setup instructions, start with the [documentation website](https://johnny-quesada-developer.github.io/react-global-state-hooks/).
|
|
1621
|
+
|
|
1622
|
+
- [Original browser demo](https://johnny-quesada-developer.github.io/global-hooks-example/)
|
|
1623
|
+
- [Original video walkthrough](https://www.youtube.com/watch?v=1UBqXk2MH8I)
|
|
1624
|
+
- [Original CodePen example](https://codepen.io/johnnynabetes/pen/WNmeGwb?editors=0010)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-hooks-global-states",
|
|
3
|
-
"version": "16.0.
|
|
3
|
+
"version": "16.0.7",
|
|
4
4
|
"description": "The shared state engine for React and React Native: selective subscriptions, derived state, actions and scoped stores.",
|
|
5
5
|
"main": "./bundle.cjs",
|
|
6
6
|
"module": "./bundle.mjs",
|
|
@@ -94,10 +94,10 @@
|
|
|
94
94
|
"bugs": {
|
|
95
95
|
"url": "https://github.com/johnny-quesada-developer/react-hooks-global-states/issues"
|
|
96
96
|
},
|
|
97
|
-
"homepage": "https://
|
|
97
|
+
"homepage": "https://johnny-quesada-developer.github.io/react-global-state-hooks/",
|
|
98
98
|
"dependencies": {
|
|
99
99
|
"json-storage-formatter": "^4.0.0",
|
|
100
|
-
"react-hooks-global-states-debug": "^16.0.
|
|
100
|
+
"react-hooks-global-states-debug": "^16.0.7"
|
|
101
101
|
},
|
|
102
102
|
"peerDependencies": {
|
|
103
103
|
"react": ">=18.0.0",
|