@t8/react-store 1.0.23 → 1.0.24

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 +53 -31
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -16,25 +16,24 @@ Installation: `npm i @t8/react-store`
16
16
  Moving the local state to the full-fledged shared state:
17
17
 
18
18
  ```diff
19
- import { createContext, useContext } from "react";
20
19
  + import { Store, useStore } from "@t8/react-store";
21
20
  +
22
- + let AppContext = createContext(new Store(0));
21
+ + let counterStore = new Store(0);
23
22
 
24
23
  let Counter = () => {
25
24
  - let [counter, setCounter] = useState(0);
26
- + let [counter, setCounter] = useStore(useContext(AppContext));
25
+ + let [counter, setCounter] = useStore(counterStore);
27
26
 
28
27
  let handleClick = () => {
29
28
  setCounter(value => value + 1);
30
29
  };
31
30
 
32
- return <button onClick={handleClick}>{counter}</button>;
31
+ return <button onClick={handleClick}>+ {counter}</button>;
33
32
  };
34
33
 
35
34
  let ResetButton = () => {
36
35
  - let [, setCounter] = useState(0);
37
- + let [, setCounter] = useStore(useContext(AppContext), false);
36
+ + let [, setCounter] = useStore(counterStore, false);
38
37
 
39
38
  let handleClick = () => {
40
39
  setCounter(0);
@@ -46,27 +45,18 @@ Moving the local state to the full-fledged shared state:
46
45
  let App = () => <><Counter/>{" "}<ResetButton/></>;
47
46
  ```
48
47
 
49
- [Live counter demo](https://codesandbox.io/p/sandbox/rtng37?file=%2Fsrc%2FPlusButton.jsx)<br>
48
+ [Live counter demo](https://codesandbox.io/p/sandbox/szhdnw?file=%252Fsrc%252FApp.tsx)<br>
50
49
  [Tic-tac-toe](https://codesandbox.io/p/sandbox/tq852v?file=%252Fsrc%252FApp.tsx)
51
50
 
52
51
  🔹 The shared state setup shown above is very similar to `useState()` allowing for quick migration from local state to shared state or the other way around.
53
52
 
54
53
  🔹 The `false` parameter in `useStore(store, false)` (as in `<ResetButton>` above) tells the hook not to subscribe the component to tracking the store state updates. The common use case is when a component makes use of the store state setter without using the store state value.
55
54
 
56
- 🔹 Note that updating the store state doesn't change the store reference sitting in the React Context and therefore doesn't cause updates of the entire React Context. Only the components subscribed to store state updates by means of `useStore()` will be notified to re-render.
57
-
58
55
  ## Single store or multiple stores
59
56
 
60
- An application can have as many stores as needed, whether on a single React Context or multiple Contexts.
57
+ An application can have as many stores as needed.
61
58
 
62
- ```js
63
- let AppContext = createContext({
64
- users: new Store(/* ... */),
65
- items: new Store(/* ... */),
66
- });
67
- ```
68
-
69
- 🔹 Splitting data into multiple stores helps maintain more targeted subscriptions to data changes in components.
59
+ 🔹 Splitting data into multiple stores is one of the strategies to maintain more targeted subscriptions to data changes in components. The other strategy is filtering store updates at the component level, which is discussed below.
70
60
 
71
61
  ## Filtering store updates
72
62
 
@@ -76,7 +66,7 @@ When only the store state setter is required, without the store state value, we
76
66
  let [, setState] = useState(store, false);
77
67
  ```
78
68
 
79
- Apart from a boolean, `useStore(store, shouldUpdate)` can take a function of `(nextState, prevState) => boolean` as the second parameter to filter store updates to respond to:
69
+ Apart from a boolean, `useStore(store, shouldUpdate)` accepts a function of `(nextState, prevState) => boolean` as the second parameter to filter store updates to respond to:
80
70
 
81
71
  ```jsx
82
72
  let ItemCard = ({ id }) => {
@@ -86,10 +76,7 @@ let ItemCard = ({ id }) => {
86
76
  return nextItems[id].revision !== prevItems[id].revision;
87
77
  }, [id]);
88
78
 
89
- let [items, setItems] = useStore(
90
- useContext(AppContext).items,
91
- hasRelevantUpdates,
92
- );
79
+ let [items, setItems] = useStore(itemStore, hasRelevantUpdates);
93
80
 
94
81
  return (
95
82
  // Content
@@ -101,15 +88,50 @@ let ItemCard = ({ id }) => {
101
88
 
102
89
  Shared state can be provided to the app by means of a regular React Context provider:
103
90
 
104
- ```diff
105
- let App = () => (
106
- - <AppContext.Provider value={42}>
107
- + <AppContext.Provider value={new Store(42)}>
108
- <PlusButton/>{" "}<Display/>
109
- </AppContext.Provider>
110
- );
91
+ ```ts
92
+ import { createContext } from "react";
93
+
94
+ export let AppContext = createContext(new Store(0));
95
+ ```
96
+
97
+ ```tsx
98
+ let App = () => (
99
+ <AppContext.Provider value={new Store(42)}>
100
+ <PlusButton/>{" "}<Display/>
101
+ </AppContext.Provider>
102
+ );
103
+ ```
104
+
105
+ ```tsx
106
+ let Counter = () => {
107
+ let [counter, setCounter] = useStore(useContext(AppContext));
108
+
109
+ // Rendering
110
+ };
111
111
  ```
112
112
 
113
+ [Live counter demo with Context](https://codesandbox.io/p/sandbox/rtng37?file=%2Fsrc%2FPlusButton.jsx)
114
+
115
+ 🔹 In a multi-store setup, stores can be located in a single Context or split across multiple Contexts, just like any application data.
116
+
117
+ ```js
118
+ // Multiple stores in a single Context
119
+ let AppContext = createContext({
120
+ users: new Store(/* ... */),
121
+ items: new Store(/* ... */),
122
+ });
123
+ ```
124
+
125
+ ```jsx
126
+ let ItemCard = ({ id }) => {
127
+ let [items, setItems] = useStore(useContext(AppContext).items);
128
+
129
+ // Rendering
130
+ };
131
+ ```
132
+
133
+ 🔹 Note that updating the store state doesn't change the store reference sitting in the React Context and therefore doesn't cause updates of the entire Context. Only the components subscribed to updates in the particular store by means of `useStore(store)` will be notified to re-render.
134
+
113
135
  ## Store data
114
136
 
115
137
  A store can contain data of any type.
@@ -128,6 +150,6 @@ Immer can be used with `useStore()` just the same way as [with `useState()`](htt
128
150
 
129
151
  The ready-to-use hook from the [T8 React Pending](https://github.com/t8js/react-pending) package helps manage shared async action state without disturbing the app's state management and actions' code.
130
152
 
131
- ## Standalone store
153
+ ## Remount-persistent state
132
154
 
133
- A store initialized outside a component can be used as the component's remount-persistent state.
155
+ A standalone store initialized outside a component can be used by the component as remount-persistent state, whether used by other components or not.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@t8/react-store",
3
- "version": "1.0.23",
3
+ "version": "1.0.24",
4
4
  "description": "Concise shared state management for React apps",
5
5
  "main": "dist/index.js",
6
6
  "type": "module",