react-global-state-hooks 16.0.5 โ†’ 16.0.6

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.
Files changed (2) hide show
  1. package/README.md +215 -144
  2. package/package.json +2 -2
package/README.md CHANGED
@@ -8,21 +8,23 @@
8
8
 
9
9
  <div align="center">
10
10
 
11
- **Shared React state. Precise subscriptions. Built-in DevTools.** ๐Ÿš€
11
+ **Shared state that feels like `useState`.**
12
12
 
13
- _The familiarity of `useState`, with the power of a shared store._
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. Persist what matters in `localStorage`. Inspect every store, action, and state change in the DevTools panel, or from your terminal.
14
14
 
15
15
  [![npm version](https://img.shields.io/npm/v/react-global-state-hooks.svg)](https://www.npmjs.com/package/react-global-state-hooks)
16
16
  [![Downloads](https://img.shields.io/npm/dm/react-global-state-hooks.svg)](https://www.npmjs.com/package/react-global-state-hooks)
17
17
  [![License](https://img.shields.io/npm/l/react-global-state-hooks.svg)](https://github.com/johnny-quesada-developer/react-global-state-hooks/blob/master/LICENSE)
18
18
 
19
- [**Live Demo**](https://johnny-quesada-developer.github.io/global-hooks-example/) โ€ข [**Video Tutorial**](https://www.youtube.com/watch?v=1UBqXk2MH8I) โ€ข [**CodePen**](https://codepen.io/johnnynabetes/pen/WNmeGwb?editors=0010)
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/)
20
+
21
+ Created by [Johnny Quesada](https://johnny-quesada-developer.github.io/react-global-state-hooks/about/), author of the React Global State Hooks family.
20
22
 
21
23
  </div>
22
24
 
23
25
  ---
24
26
 
25
- ## ๐ŸŽฏ The One-Liner
27
+ ## Start with a single hook
26
28
 
27
29
  ```tsx
28
30
  import { createGlobalState } from 'react-global-state-hooks';
@@ -30,7 +32,7 @@ import { createGlobalState } from 'react-global-state-hooks';
30
32
  export const useCounter = createGlobalState(0);
31
33
  ```
32
34
 
33
- **That's it.** No providers. No context boilerplate. No configuration files. Shared state with a familiar React API.
35
+ A shared store, ready to use. Global hooks work without a provider; use `createContext` when a subtree needs its own instance.
34
36
 
35
37
  ```tsx
36
38
  // Use it anywhere, instantly
@@ -42,35 +44,42 @@ function Counter() {
42
44
 
43
45
  ---
44
46
 
45
- ## ๐Ÿš€ Built for React applications
47
+ ## Built for React applications
48
+
49
+ ### **Familiar React API**
46
50
 
47
- ### ๐ŸŽ“ **Familiar React API**
51
+ If you know `useState`, you already know the API.
48
52
 
49
53
  ```tsx
50
- // If you know this...
51
- const [state, setState] = useState(0);
54
+ // Local state
55
+ const [count, setCount] = useState(0);
52
56
 
53
- // You know this!
54
- const [state, setState] = useGlobalState();
57
+ // Shared state
58
+ const [count, setCount] = useCounter();
55
59
  ```
56
60
 
57
- ### โšก **Precise subscriptions**
61
+ ### **Precise Subscriptions**
58
62
 
59
- 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.
60
64
 
61
65
  ```tsx
62
66
  // Only re-renders when name changes
63
- const [name] = useStore((s) => s.user.name);
67
+ const [name] = useStore((state) => state.user.name);
64
68
  ```
65
69
 
66
- ### ๐Ÿ”— **Chainable Selectors**
70
+ ### **Chainable Selectors**
71
+
72
+ Build reusable state hooks on top of other selector hooks.
67
73
 
68
74
  ```tsx
69
- const useUsers = useStore.createSelectorHook((s) => s.users);
70
- const useAdmins = useUsers.createSelectorHook((users) => users.filter((u) => u.isAdmin));
75
+ const useUsers = useStore.createSelectorHook((state) => state.users);
76
+
77
+ const useAdmins = useUsers.createSelectorHook((users) => users.filter((user) => user.isAdmin));
71
78
  ```
72
79
 
73
- ### ๐ŸŽญ **Actions (Optional)**
80
+ ### **Actions (Optional)**
81
+
82
+ Keep mutation logic next to the store when a feature needs more structure.
74
83
 
75
84
  ```tsx
76
85
  const useAuth = createGlobalState(null, {
@@ -78,6 +87,7 @@ const useAuth = createGlobalState(null, {
78
87
  login(credentials) {
79
88
  return async ({ setState }) => {
80
89
  const user = await api.login(credentials);
90
+
81
91
  setState(user);
82
92
  };
83
93
  },
@@ -85,7 +95,9 @@ const useAuth = createGlobalState(null, {
85
95
  });
86
96
  ```
87
97
 
88
- ### ๐ŸŽช **Context Mode**
98
+ ### **Context Mode**
99
+
100
+ Need an isolated instance instead of app-wide state? Same state model, inside a provider.
89
101
 
90
102
  ```tsx
91
103
  const Form = createContext({ name: '', email: '' });
@@ -95,19 +107,59 @@ const Form = createContext({ name: '', email: '' });
95
107
  </Form.Provider>;
96
108
  ```
97
109
 
98
- ### ๐Ÿ“ฆ **Non-Reactive API**
110
+ ### **Persistence with localStorage**
111
+
112
+ Keep preferences and drafts across browser sessions.
113
+
114
+ ```tsx
115
+ const useSettings = createGlobalState(
116
+ { theme: 'dark' },
117
+ {
118
+ localStorage: {
119
+ key: 'settings',
120
+ },
121
+ },
122
+ );
123
+ ```
124
+
125
+ ### **Non-Reactive API**
99
126
 
100
- Use state anywhere - even outside React components!
127
+ Read, update, or subscribe to state outside React components.
101
128
 
102
129
  ```tsx
103
- // In API interceptors, WebSockets, utils...
104
130
  const token = useAuth.getState().token;
105
- useAuth.setState({ user: newUser });
131
+
132
+ useAuth.setState({ user: nextUser });
106
133
  ```
107
134
 
108
135
  ---
109
136
 
110
- ## ๐Ÿ“ฆ Installation
137
+ ## Agentic DevTools
138
+
139
+ 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.
140
+
141
+ ```bash
142
+ npm install --save-dev ws # rgsh talks to the extension over a local WebSocket
143
+ npx rgsh --list # every store DevTools knows about, with its actions
144
+ npx rgsh action todos add "Write the docs" # run an action; prints each changed path, before โ†’ after
145
+ npx rgsh state todos todos[0].done # read the result back
146
+ ```
147
+
148
+ Import the debug entry first in your **development** entry file, before any module that creates a store, and keep it out of production builds:
149
+
150
+ ```ts
151
+ import 'react-global-state-hooks/debug';
152
+ ```
153
+
154
+ `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.
155
+
156
+ | The app being inspected | Stores, actions, and state diffs in the panel |
157
+ | ------------------------- | ----------------------------------------------- |
158
+ | <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"> |
159
+
160
+ ---
161
+
162
+ ## Installation
111
163
 
112
164
  ```bash
113
165
  npm install react-global-state-hooks
@@ -120,9 +172,9 @@ npm install react-global-state-hooks
120
172
 
121
173
  ---
122
174
 
123
- ## ๐ŸŽฌ Quick Start
175
+ ## Quick Start
124
176
 
125
- ### 30 Seconds to Global State
177
+ ### Your first shared store
126
178
 
127
179
  ```tsx
128
180
  import { createGlobalState } from 'react-global-state-hooks';
@@ -195,13 +247,13 @@ function LoginButton({ authenticate }: { authenticate: () => Promise<User> }) {
195
247
 
196
248
  ---
197
249
 
198
- ## ๐ŸŒŸ Core Features Deep Dive
250
+ ## Core Features Deep Dive
199
251
 
200
- ### 1๏ธโƒฃ Global State with `createGlobalState`
252
+ ### Global State with `createGlobalState`
201
253
 
202
- Create state that lives outside React's component tree. Perfect for app-wide state!
254
+ Keep app-wide state outside the component tree and subscribe wherever it is needed.
203
255
 
204
- #### ๐ŸŽจ The Basics
256
+ #### The Basics
205
257
 
206
258
  ```tsx
207
259
  // Primitives
@@ -224,7 +276,7 @@ const useExpensiveState = createGlobalState(() => {
224
276
  });
225
277
  ```
226
278
 
227
- #### ๐ŸŽฏ Surgical Re-renders with Selectors
279
+ #### Focused subscriptions with Selectors
228
280
 
229
281
  Selectors keep components subscribed to the state they use.
230
282
 
@@ -273,7 +325,7 @@ function NotificationCount() {
273
325
  | `useStore()` | Any store value change |
274
326
  | `useStore(selector)` | A change to the selected value |
275
327
 
276
- #### โšก Computed Values with Dependencies
328
+ #### Computed Values with Dependencies
277
329
 
278
330
  Derive values from both store state and component-local values, with explicit dependencies.
279
331
 
@@ -351,7 +403,7 @@ function AdvancedFiltered() {
351
403
  }
352
404
  ```
353
405
 
354
- #### ๐Ÿ”— Reusable Selector Hooks
406
+ #### Reusable Selector Hooks
355
407
 
356
408
  Compose reusable selector hooks. Each hook returns its selected value directly.
357
409
 
@@ -416,7 +468,7 @@ function ActivateAll() {
416
468
  }
417
469
  ```
418
470
 
419
- **Why this is powerful:**
471
+ **Selector composition:**
420
472
 
421
473
  | Feature | Benefit |
422
474
  | -------------------- | ------------------------------------------ |
@@ -426,9 +478,9 @@ function ActivateAll() {
426
478
  | ๐ŸŽจ **Clean Code** | No repetitive selector logic in components |
427
479
  | โšก **Performance** | Automatic memoization and change detection |
428
480
 
429
- #### ๐ŸŽฌ Actions - When You Need Structure
481
+ #### Actions - When You Need Structure
430
482
 
431
- Actions aren't required, but they're awesome for organizing mutations!
483
+ Add actions to give your store a clear, reusable mutation API.
432
484
 
433
485
  ```tsx
434
486
  const useStore = createGlobalState(
@@ -519,15 +571,15 @@ function TodoApp() {
519
571
  );
520
572
  }
521
573
 
522
- // ๐Ÿค  Don't worry, you can still go rogue with setState!
574
+ // Direct updates remain available through setState.
523
575
  const handleQuickFix = () => {
524
576
  useStore.setState((s) => ({ ...s, filter: 'all' }));
525
577
  };
526
578
  ```
527
579
 
528
- #### ๐Ÿ”Œ Non-Reactive API (Use Outside React!)
580
+ #### Store access outside React
529
581
 
530
- Access your state from _anywhere_ - even outside components!
582
+ Use the same store API in components, services, and background workflows.
531
583
 
532
584
  ```tsx
533
585
  const useAuth = createGlobalState({ user: null, token: null });
@@ -569,9 +621,9 @@ const unsubscribe = useAuth.subscribe(
569
621
  );
570
622
  ```
571
623
 
572
- #### ๐Ÿ”ญ Observable Fragments
624
+ #### Observable Fragments
573
625
 
574
- Create observable slices of your state for reactive programming!
626
+ Create observable state slices for subscriptions outside React.
575
627
 
576
628
  ```tsx
577
629
  const useStore = createGlobalState({
@@ -597,7 +649,7 @@ console.log(countObservable.getState()); // Current count value
597
649
  const doubledObservable = countObservable.createObservable((count) => count * 2);
598
650
  ```
599
651
 
600
- #### ๐Ÿ“‹ Metadata - Non-Reactive Side Info
652
+ #### Metadata - Non-Reactive Side Info
601
653
 
602
654
  Keep request counters and timestamps in metadata when they are read only by handlers or background work.
603
655
  Put loading indicators and displayed errors in state so components subscribe to their changes.
@@ -621,11 +673,11 @@ function recordFetchedItems(items: string[]) {
621
673
 
622
674
  ---
623
675
 
624
- ### ๐Ÿ’พ Persisted State with localStorage
676
+ ### Persisted State with localStorage
625
677
 
626
- This package comes with **built-in localStorage integration**! The key insight: **just add a `key` property** and your state automatically persists across browser sessions. No setup, no configuration files, no extra code.
678
+ Keep preferences and drafts across browser sessions with built-in localStorage integration. Add `localStorage: { key }` to a store; the library handles saving and restoration.
627
679
 
628
- ### ๐ŸŽจ Basic Persistence
680
+ ### Basic Persistence
629
681
 
630
682
  ```tsx
631
683
  import { createGlobalState } from 'react-global-state-hooks';
@@ -640,30 +692,30 @@ const useSettings = createGlobalState(
640
692
  );
641
693
  ```
642
694
 
643
- **That's literally all you need!** Your state will automatically:
695
+ With persistence enabled, the store will:
644
696
 
645
697
  - โœ… Save to localStorage on every change
646
698
  - โœ… Restore from localStorage on initialization
647
699
  - โœ… Handle JSON serialization/deserialization
648
- - โœ… Work with any data type (objects, arrays, primitives)
700
+ - โœ… Persist objects, arrays, and primitive values
649
701
 
650
- ### ๐Ÿ”’ Safe Persistence with Validation (Optional)
702
+ ### Safe Persistence with Validation (Optional)
651
703
 
652
704
  The `validator` is **completely optional**. Add it only when you need to validate or transform restored data:
653
705
 
654
706
  ```tsx
655
707
  import { createGlobalState } from 'react-global-state-hooks';
708
+ import { z } from 'zod';
709
+
710
+ const contacts = z.map(z.string(), z.object({ email: z.string() }));
656
711
 
657
- const useContacts = createGlobalState(new Map(), {
712
+ const useContacts = createGlobalState(new Map<string, { email: string }>(), {
658
713
  localStorage: {
659
714
  key: 'contacts',
660
715
 
661
- // Optional: validate/transform restored data
662
- validator: ({ restored, initial }) => {
663
- // Validate the restored value
664
- if (!isMap(restored)) return initial;
665
- return restored as typeof initial;
666
- },
716
+ // Optional: validate/transform restored data. A schema library makes this one line, because a
717
+ // throw is caught by the store and the initial state is kept.
718
+ validator: ({ restored }) => contacts.parse(restored),
667
719
  },
668
720
  });
669
721
  ```
@@ -676,20 +728,31 @@ const useContacts = createGlobalState(new Map(), {
676
728
  - Return a value โ†’ That value becomes the new state
677
729
  - Return `undefined` โ†’ The restored data is used as-is
678
730
  - Return `initial` โ†’ Falls back to initial state (validation failed)
731
+ - Throw โ†’ Same as returning `initial`, and the error reaches `onError`. This is what lets a schema
732
+ library be the whole validator
733
+ - Validate the state, not the fragment. `restored` holds only what the `selector` saved, so merge it over
734
+ `initial` first: `({ restored, initial }) => schema.parse({ ...initial, ...restored })`
679
735
 
680
736
  **When to use validator:**
681
737
 
682
738
  - โœ… You changed your data structure and need to migrate old data
683
739
  - โœ… You want to validate data integrity
684
740
  - โœ… You need to transform restored data
685
- - โŒ Simple use cases - validator is not required!
741
+ For simple cases, you can omit the validator.
686
742
 
687
- ### ๐Ÿ”„ Versioning & Migration (Optional)
743
+ ### Versioning & Migration (Optional)
688
744
 
689
745
  Handle breaking changes gracefully with optional versioning:
690
746
 
691
747
  ```tsx
692
748
  import { createGlobalState } from 'react-global-state-hooks';
749
+ import { z } from 'zod';
750
+
751
+ const prefs = z.object({
752
+ theme: z.enum(['dark', 'light']),
753
+ notifications: z.boolean(),
754
+ language: z.string(),
755
+ });
693
756
 
694
757
  const useUserPrefs = createGlobalState(
695
758
  { theme: 'dark', notifications: true, language: 'en' },
@@ -715,12 +778,7 @@ const useUserPrefs = createGlobalState(
715
778
  },
716
779
 
717
780
  // Optional: validate after migration
718
- validator: ({ restored, initial }) => {
719
- if (typeof restored === 'object' && restored !== null) {
720
- return { ...initial, ...restored };
721
- }
722
- return initial;
723
- },
781
+ validator: ({ restored, initial }) => prefs.parse({ ...initial, ...(restored as object) }),
724
782
  },
725
783
  },
726
784
  );
@@ -734,18 +792,22 @@ const useUserPrefs = createGlobalState(
734
792
  4. After migration, `validator` runs (if provided)
735
793
  5. New version is saved to localStorage
736
794
 
737
- ### ๐ŸŽฏ Selective Persistence (Optional)
795
+ ### Selective Persistence (Optional)
738
796
 
739
797
  Only persist specific parts of your state:
740
798
 
741
799
  ```tsx
742
800
  import { createGlobalState } from 'react-global-state-hooks';
801
+ import { z } from 'zod';
743
802
 
744
- type AppState = {
745
- user: { name: string; email: string };
746
- settings: { theme: string };
747
- sessionData: { temp: string }; // Don't persist this!
748
- };
803
+ // The whole state gets a schema, even the part that is never saved
804
+ const appState = z.object({
805
+ user: z.object({ name: z.string(), email: z.string() }),
806
+ settings: z.object({ theme: z.string() }),
807
+ sessionData: z.object({ temp: z.string() }), // Don't persist this!
808
+ });
809
+
810
+ type AppState = z.infer<typeof appState>;
749
811
 
750
812
  const initialAppState: AppState = {
751
813
  user: { name: 'Guest', email: '' },
@@ -765,24 +827,18 @@ const useAppState = createGlobalState(
765
827
  settings: state.settings,
766
828
  }),
767
829
 
768
- // Optional: merge persisted data with initial state
769
- validator: ({ restored, initial }) => {
770
- if (typeof restored === 'object' && restored !== null) {
771
- // Merge persisted data with initial (to get sessionData)
772
- return { ...initial, ...restored };
773
- }
774
- return initial;
775
- },
830
+ // Storage only carries user and settings, so validate the state they produce
831
+ validator: ({ restored, initial }) => appState.parse({ ...initial, ...(restored as Partial<AppState>) }),
776
832
  },
777
833
  },
778
834
  );
779
835
  ```
780
836
 
781
- ### 2๏ธโƒฃ Scoped State with `createContext`
837
+ ### Scoped State with `createContext`
782
838
 
783
- Sometimes you need state scoped to a component tree. That's what `createContext` is for!
839
+ Use `createContext` to give each provider its own store instance.
784
840
 
785
- #### ๐ŸŽช The Basics
841
+ #### The Basics
786
842
 
787
843
  ```tsx
788
844
  import { createContext } from 'react-global-state-hooks';
@@ -824,7 +880,7 @@ function FormPreview() {
824
880
  }
825
881
  ```
826
882
 
827
- #### ๐ŸŽ Provider Variations
883
+ #### Provider Variations
828
884
 
829
885
  ```tsx
830
886
  const ThemeContext = createContext('light');
@@ -851,7 +907,7 @@ function App() {
851
907
  }
852
908
  ```
853
909
 
854
- #### ๐ŸŽฏ Context + Selectors = โค๏ธ
910
+ #### Context selectors
855
911
 
856
912
  Use the same selectors, actions and metadata with state scoped to each provider.
857
913
 
@@ -880,7 +936,7 @@ function EmailField() {
880
936
  }
881
937
  ```
882
938
 
883
- #### ๐ŸŽญ Context with Actions
939
+ #### Context with Actions
884
940
 
885
941
  ```tsx
886
942
  const CounterContext = createContext(0, {
@@ -923,9 +979,9 @@ function App() {
923
979
  }
924
980
  ```
925
981
 
926
- #### ๐Ÿ”— Reusable Context Selectors
982
+ #### Reusable Context Selectors
927
983
 
928
- Yes, chainable selectors work here too!
984
+ Compose reusable selectors for scoped stores with the same API.
929
985
 
930
986
  ```tsx
931
987
  const DataContext = createContext({
@@ -960,9 +1016,9 @@ function UserList() {
960
1016
  }
961
1017
  ```
962
1018
 
963
- #### ๐Ÿงช What About Testing?
1019
+ #### Testing context stores
964
1020
 
965
- Do you need to access the context to spy on state changes, inject test data, or manipulate state directly? No problem!
1021
+ Access the context store directly to inspect changes, inject test data, and exercise updates.
966
1022
 
967
1023
  ```tsx
968
1024
  import { renderHook } from '@testing-library/react';
@@ -988,9 +1044,9 @@ describe('CounterContext', () => {
988
1044
  });
989
1045
  ```
990
1046
 
991
- #### ๐ŸŽฌ Lifecycle Hooks
1047
+ #### Lifecycle Hooks
992
1048
 
993
- React to context lifecycle events!
1049
+ Connect initialization and cleanup to the context lifecycle.
994
1050
 
995
1051
  ```tsx
996
1052
  const DataContext = createContext([], {
@@ -1030,11 +1086,11 @@ function App() {
1030
1086
 
1031
1087
  ---
1032
1088
 
1033
- ### 3๏ธโƒฃ External Actions with `actions`
1089
+ ### External Actions with `actions`
1034
1090
 
1035
- Extend any store with additional actions without modifying it! Perfect for separating concerns! ๐ŸŽฏ
1091
+ Define actions in focused modules and bind them to an existing store.
1036
1092
 
1037
- #### ๐Ÿ’ช Direct Binding
1093
+ #### Direct Binding
1038
1094
 
1039
1095
  ```tsx
1040
1096
  import { createGlobalState, actions } from 'react-global-state-hooks';
@@ -1068,9 +1124,9 @@ counterActions.double(); // count = 10
1068
1124
  counterActions.decrement(3); // count = 7
1069
1125
  ```
1070
1126
 
1071
- #### ๐ŸŽจ Action Templates (Define Before Ready!)
1127
+ #### Action templates
1072
1128
 
1073
- Need actions in contexts or lifecycle hooks (onInit) before the store API is available? Create action templates first, bind them later!
1129
+ Define action templates before the store API is available, then bind them in a context or lifecycle callback.
1074
1130
 
1075
1131
  ```tsx
1076
1132
  import { actions, InferAPI, createContext } from 'react-global-state-hooks';
@@ -1121,9 +1177,9 @@ const { loadData } = SessionContext.use.actions();
1121
1177
  console.log(loadData); // undefined
1122
1178
  ```
1123
1179
 
1124
- #### ๐Ÿ”„ Actions Calling Actions
1180
+ #### Actions Calling Actions
1125
1181
 
1126
- Actions can call each other in multiple ways!
1182
+ Compose actions into larger workflows.
1127
1183
 
1128
1184
  ```tsx
1129
1185
  const useStore = createGlobalState({ count: 0, history: [] }, {
@@ -1170,9 +1226,9 @@ const storeActions = actions(useStore, {
1170
1226
  storeActions.incrementTwice(5);
1171
1227
  ```
1172
1228
 
1173
- #### ๐ŸŽญ Access Store Actions
1229
+ #### Access Store Actions
1174
1230
 
1175
- External actions can call each other with `this` and access the store's public actions!
1231
+ External actions can call each other with `this` and access the store's public actions.
1176
1232
 
1177
1233
  ```tsx
1178
1234
  const useStore = createGlobalState(
@@ -1211,7 +1267,7 @@ const extraActions = actions(useStore, {
1211
1267
  extraActions.incrementAndLog(5);
1212
1268
  ```
1213
1269
 
1214
- #### ๐ŸŽช Works with Context!
1270
+ #### Actions in context stores
1215
1271
 
1216
1272
  ```tsx
1217
1273
  import { actions, InferAPI } from 'react-global-state-hooks';
@@ -1260,11 +1316,11 @@ function Counter() {
1260
1316
 
1261
1317
  ---
1262
1318
 
1263
- ## ๐Ÿ”ฅ Advanced Patterns
1319
+ ## Advanced Patterns
1264
1320
 
1265
- ### ๐Ÿ—๏ธ Production Architecture (File Organization)
1321
+ ### Production Architecture (File Organization)
1266
1322
 
1267
- Real-world large-scale applications need clean separation! Here's how to organize a store with actions in separate files, custom hooks, observables, and a namespace pattern:
1323
+ Keep each domain easy to navigate with dedicated modules for its store, actions, selector hooks, and observables:
1268
1324
 
1269
1325
  **File Structure:**
1270
1326
 
@@ -1450,9 +1506,9 @@ function TodoApp() {
1450
1506
  - โœ… **Namespace pattern** - Everything bundled: `todos$.useActiveTodos()`, `todos$.activeTodos$`
1451
1507
  - โœ… **Scalable** - Easy to find, test, and maintain individual pieces
1452
1508
 
1453
- ### ๐ŸŽง Smart Subscriptions
1509
+ ### Smart Subscriptions
1454
1510
 
1455
- Subscribe to specific slices outside React!
1511
+ Subscribe to the state slice your integration needs.
1456
1512
 
1457
1513
  ```tsx
1458
1514
  const useStore = createGlobalState({
@@ -1486,11 +1542,11 @@ unsubRole();
1486
1542
 
1487
1543
  ---
1488
1544
 
1489
- ## ๐ŸŽจ `uniqueId` - Type-Safe Unique IDs
1545
+ ## `uniqueId` - Type-Safe Unique IDs
1490
1546
 
1491
- Generate branded unique identifiers with compile-time safety!
1547
+ Generate unique identifiers with branded types that distinguish one domain from another.
1492
1548
 
1493
- ### ๐Ÿท๏ธ Basic Usage
1549
+ ### Basic Usage
1494
1550
 
1495
1551
  ```tsx
1496
1552
  import { uniqueId } from 'react-global-state-hooks';
@@ -1501,9 +1557,9 @@ const id2 = uniqueId('user:'); // "user:a1b2c3d4-e5f6-7890-abcd-ef1234567890"
1501
1557
  const id3 = uniqueId('session:'); // "session:a1b2c3d4-e5f6-7890-abcd-ef1234567890"
1502
1558
  ```
1503
1559
 
1504
- ### ๐Ÿ”’ Branded IDs (Type Safety!)
1560
+ ### Branded identifiers
1505
1561
 
1506
- Create ID generators with compile-time type checking!
1562
+ Create ID generators with compile-time type checking.
1507
1563
 
1508
1564
  ```tsx
1509
1565
  // Create branded generators
@@ -1520,7 +1576,7 @@ const postId: PostId = generatePostId(); // โœ… "post:a1b2c3d4-e5f6-7890-abcd-ef
1520
1576
  const wrong: UserId = generatePostId(); // โŒ Type error!
1521
1577
  ```
1522
1578
 
1523
- ### ๐Ÿ›ก๏ธ Runtime Validation
1579
+ ### Runtime Validation
1524
1580
 
1525
1581
  ```tsx
1526
1582
  const generateUserId = uniqueId.for('user:');
@@ -1540,9 +1596,9 @@ generateUserId.assert('user:a1b2c3d4-e5f6-7890-abcd-ef1234567890'); // โœ… OK
1540
1596
  generateUserId.assert('post:a1b2c3d4-e5f6-7890-abcd-ef1234567890'); // โŒ Throws error!
1541
1597
  ```
1542
1598
 
1543
- ### ๐ŸŽฏ Strict Branding
1599
+ ### Strict Branding
1544
1600
 
1545
- Maximum type safety with symbol branding!
1601
+ Use symbol branding to distinguish identifier types even when their prefixes match.
1546
1602
 
1547
1603
  ```tsx
1548
1604
  declare const UserBrand: unique symbol;
@@ -1561,7 +1617,7 @@ const id1: UserId = generateUserId(); // โœ…
1561
1617
  const id2: UserId = generateUserId2(); // โŒ Different brands!
1562
1618
  ```
1563
1619
 
1564
- ### ๐Ÿ’ผ Real-World Example
1620
+ ### Real-World Example
1565
1621
 
1566
1622
  ```tsx
1567
1623
  import { createGlobalState, uniqueId } from 'react-global-state-hooks';
@@ -1643,44 +1699,50 @@ actions.addTodo('Build feature', userId);
1643
1699
 
1644
1700
  ---
1645
1701
 
1646
- ## ๐ŸŽ“ Learning Resources
1702
+ ## Documentation and examples
1703
+
1704
+ The [React Global State Hooks website](https://johnny-quesada-developer.github.io/react-global-state-hooks/) is the home for current documentation,
1705
+ interactive examples, and the DevTools walkthrough.
1647
1706
 
1648
- | Resource | Description |
1649
- | ------------------------------------------------------------------------------------ | --------------------------------- |
1650
- | ๐ŸŽฎ [**Live Demo**](https://johnny-quesada-developer.github.io/global-hooks-example/) | Interactive examples |
1651
- | ๐ŸŽฅ [**Video Tutorial**](https://www.youtube.com/watch?v=1UBqXk2MH8I) | Full walkthrough |
1652
- | ๐Ÿ’ป [**CodePen**](https://codepen.io/johnnynabetes/pen/WNmeGwb?editors=0010) | Try it online |
1653
- | ๐Ÿ“š **400+ Tests** | Check the test suite for patterns |
1707
+ | Explore | What you will find |
1708
+ | --- | --- |
1709
+ | [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. |
1710
+ | [API and guides](https://johnny-quesada-developer.github.io/react-global-state-hooks/docs/) | Selectors, actions, scoped state, persistence, and TypeScript. |
1711
+ | [Interactive examples](https://johnny-quesada-developer.github.io/react-global-state-hooks/examples/) | Explore the state model in working browser examples. |
1712
+ | [DevTools](https://johnny-quesada-developer.github.io/react-global-state-hooks/docs/devtools/) | Inspect state, follow actions, and use the terminal workflow. |
1713
+ | [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. |
1714
+ | [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. |
1654
1715
 
1655
1716
  ---
1656
1717
 
1657
- ## ๐ŸŒ Platform-Specific Versions
1718
+ ## Choose your package
1658
1719
 
1659
- | Package | Platform | Special Feature |
1660
- | -------------------------------------------------------------------------------------------------- | -------------------- | ------------------------ |
1661
- | [`react-hooks-global-states`](https://www.npmjs.com/package/react-hooks-global-states) | React / React Native | Core library |
1662
- | [`react-global-state-hooks`](https://www.npmjs.com/package/react-global-state-hooks) | Web | localStorage integration |
1663
- | [`react-native-global-state-hooks`](https://www.npmjs.com/package/react-native-global-state-hooks) | React Native | AsyncStorage integration |
1720
+ The family shares a common state API, with persistence tailored to each platform.
1664
1721
 
1665
- ---
1722
+ | Package | Best fit |
1723
+ | --- | --- |
1724
+ | [`react-global-state-hooks`](https://www.npmjs.com/package/react-global-state-hooks) | React web applications with optional localStorage persistence. |
1725
+ | [`react-native-global-state-hooks`](https://www.npmjs.com/package/react-native-global-state-hooks) | React Native applications with optional asynchronous persistence. |
1726
+ | [`react-hooks-global-states`](https://www.npmjs.com/package/react-hooks-global-states) | The shared core without platform-specific persistence. |
1727
+ | [`react-hooks-global-states-debug`](https://www.npmjs.com/package/react-hooks-global-states-debug) | Development instrumentation for the DevTools extension. |
1666
1728
 
1667
- ## ๐ŸŽ‰ Why Developers Choose This
1729
+ See the [platform guide](https://johnny-quesada-developer.github.io/react-global-state-hooks/docs/platform-and-versions/) for package differences
1730
+ and the [DevTools guide](https://johnny-quesada-developer.github.io/react-global-state-hooks/docs/devtools/) for debug entry points.
1668
1731
 
1669
- ### At a glance
1732
+ ---
1733
+
1734
+ ## Built to grow with your application
1670
1735
 
1671
- | What You Get | What You Don't |
1672
- | --------------------------- | --------------------- |
1673
- | โœ… `useState` API | โŒ Boilerplate |
1674
- | โœ… Surgical re-renders | โŒ Whole-tree updates |
1675
- | โœ… Chainable selectors | โŒ Repetitive code |
1676
- | โœ… TypeScript inference | โŒ Manual typing |
1677
- | โœ… Global + Context | โŒ Either/or choice |
1678
- | โœ… Actions (optional) | โŒ Required structure |
1679
- | โœ… Familiar hook syntax | โŒ New component APIs |
1736
+ - **Familiar from the first hook.** Share state through a `useState`-style API.
1737
+ - **Focused subscriptions.** Select the values a component needs.
1738
+ - **Composable structure.** Bring in actions, selectors, and scoped stores as your features grow.
1739
+ - **Persistence where you need it.** Keep selected state in `localStorage` across browser sessions.
1740
+ - **A connected debugging workflow.** Follow state and actions with the [DevTools integration](https://johnny-quesada-developer.github.io/react-global-state-hooks/docs/devtools/).
1741
+ - **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/).
1680
1742
 
1681
1743
  ---
1682
1744
 
1683
- ## ๐Ÿš€ Get Started Now
1745
+ ## Get Started Now
1684
1746
 
1685
1747
  ```bash
1686
1748
  npm install react-global-state-hooks
@@ -1699,14 +1761,23 @@ function App() {
1699
1761
  }
1700
1762
  ```
1701
1763
 
1702
- **That's it. You're done.** ๐ŸŽ‰
1764
+ Continue with the [guides and interactive examples](https://johnny-quesada-developer.github.io/react-global-state-hooks/) to build your next store.
1703
1765
 
1704
1766
  ---
1705
1767
 
1706
- <div align="center">
1768
+ ## Built by Johnny Quesada
1707
1769
 
1708
- ### Built with โค๏ธ for developers who value simplicity
1770
+ 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/),
1771
+ and help shape what comes next. If the library helps your work, a GitHub star or a
1772
+ shared example helps more developers discover it.
1709
1773
 
1710
- **[โญ Star on GitHub](https://github.com/johnny-quesada-developer/react-global-state-hooks)** โ€ข **[๐Ÿ“ Report Issues](https://github.com/johnny-quesada-developer/react-global-state-hooks/issues)** โ€ข **[๐Ÿ’ฌ Discussions](https://github.com/johnny-quesada-developer/react-global-state-hooks/discussions)**
1774
+ [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/web)
1711
1775
 
1712
- </div>
1776
+ ## Legacy resources
1777
+
1778
+ Earlier demos and walkthroughs are preserved here for reference. For current APIs,
1779
+ examples, and setup instructions, start with the [documentation website](https://johnny-quesada-developer.github.io/react-global-state-hooks/).
1780
+
1781
+ - [Original browser demo](https://johnny-quesada-developer.github.io/global-hooks-example/)
1782
+ - [Original video walkthrough](https://www.youtube.com/watch?v=1UBqXk2MH8I)
1783
+ - [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-global-state-hooks",
3
- "version": "16.0.5",
3
+ "version": "16.0.6",
4
4
  "description": "Shared React state with a useState-style API, selective subscriptions, actions, localStorage persistence and DevTools.",
5
5
  "main": "./bundle.cjs",
6
6
  "module": "./bundle.mjs",
@@ -103,7 +103,7 @@
103
103
  "homepage": "https://github.com/johnny-quesada-developer/react-global-state-hooks#readme",
104
104
  "dependencies": {
105
105
  "json-storage-formatter": "^4.0.0",
106
- "react-hooks-global-states": "^16.0.5"
106
+ "react-hooks-global-states": "^16.0.6"
107
107
  },
108
108
  "peerDependencies": {
109
109
  "json-storage-formatter": "^4.0.0",