react-global-state-hooks 1.0.13 → 1.0.15
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 +229 -60
- package/lib/GlobalStore.d.ts +43 -48
- package/lib/GlobalStore.d.ts.map +1 -1
- package/lib/GlobalStore.js +88 -157
- package/lib/GlobalStore.types.d.ts +25 -0
- package/lib/GlobalStore.types.d.ts.map +1 -0
- package/lib/{GlobalStoreTypes.js → GlobalStore.types.js} +0 -0
- package/package.json +2 -2
- package/README.advance.md +0 -123
- package/lib/GlobalStoreTypes.d.ts +0 -54
- package/lib/GlobalStoreTypes.d.ts.map +0 -1
package/README.md
CHANGED
|
@@ -1,86 +1,113 @@
|
|
|
1
1
|
# react-global-state-hooks
|
|
2
|
-
This is a package to easily handling global-state across your react-components **No-redux**, **No-context**
|
|
3
2
|
|
|
4
|
-
This
|
|
3
|
+
This is a package to easily handling global-state across your react components
|
|
5
4
|
|
|
6
|
-
|
|
5
|
+
This utility uses the **useState** hook within a subscription pattern and **HOFs** to create a more intuitive, atomic and easy way of sharing state between components
|
|
7
6
|
|
|
8
|
-
|
|
7
|
+
...
|
|
9
8
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
9
|
+
...
|
|
10
|
+
|
|
11
|
+
# Creating a global store
|
|
12
|
+
|
|
13
|
+
We are gonna create a global count example **useCountGlobal.ts**:
|
|
14
|
+
|
|
15
|
+
```ts
|
|
16
|
+
import { GlobalStore } from 'react-global-state-hooks';
|
|
13
17
|
|
|
14
18
|
// initialize your store with the default value of the same.
|
|
15
19
|
const countStore = new GlobalStore(0);
|
|
16
20
|
|
|
17
|
-
//
|
|
21
|
+
// get the hook
|
|
18
22
|
export const useCountGlobal = countStore.getHook();
|
|
19
23
|
|
|
24
|
+
// inside your component just call...
|
|
25
|
+
const [count, setCount] = useCountGlobal(); // no paremeters are needed since this is a global store
|
|
26
|
+
|
|
20
27
|
// That's it, that's a global store... Strongly typed, with a global-hook that we could reuse cross all our react-components.
|
|
28
|
+
|
|
29
|
+
// #### Optionally you are able to use a decoupled hook,
|
|
30
|
+
// #### This function is linked to the store hooks but is not a hook himself.
|
|
31
|
+
|
|
32
|
+
export const [getCount, sendCount] = countStore.getHookDecoupled();
|
|
33
|
+
|
|
34
|
+
// @example
|
|
35
|
+
console.log(getCount()); // 0;
|
|
36
|
+
|
|
37
|
+
// components subscribed to the global hook if there are so
|
|
38
|
+
sendCount(5);
|
|
39
|
+
|
|
40
|
+
console.log(getCount()); // 5;
|
|
21
41
|
```
|
|
22
42
|
|
|
23
|
-
|
|
24
|
-
|
|
43
|
+
...
|
|
44
|
+
|
|
45
|
+
...
|
|
46
|
+
|
|
47
|
+
# Implementing your global hook into your components
|
|
48
|
+
|
|
49
|
+
Let's say we have two components **MyFirstComponent**, **MySecondComponent**, in order to use our global hook they will look just like:
|
|
25
50
|
|
|
26
51
|
```JSX
|
|
27
|
-
import { useCountGlobal } from './
|
|
52
|
+
import { useCountGlobal } from './useCountGlobal'
|
|
28
53
|
|
|
29
54
|
const MyFirstComponent: React.FC = () => {
|
|
30
55
|
const [count, setter] = useCountGlobal();
|
|
31
|
-
const
|
|
56
|
+
const onClickAddOne = () => setter(count + 1);
|
|
32
57
|
|
|
33
|
-
return (<button
|
|
58
|
+
return (<button onClick={onClickAddOne}>{`count: ${count}`}</button>);
|
|
34
59
|
}
|
|
35
60
|
|
|
36
61
|
const MySecondComponent: React.FC = () => {
|
|
37
62
|
const [count, setter] = useCountGlobal();
|
|
38
|
-
const onClick = useCallback(() => setter(currentState => currentState + 1));
|
|
39
63
|
|
|
40
|
-
|
|
64
|
+
// it can also be use as a normal setter into a callback or other hooks
|
|
65
|
+
const onClickAddTwo = useCallback(() => setter(state => state + 2), [])
|
|
66
|
+
|
|
67
|
+
return (<button onClick={onClickAddOne}>{`count: ${count}`}</button>);
|
|
41
68
|
}
|
|
42
69
|
|
|
43
|
-
//
|
|
70
|
+
// It's so simple to share information between components
|
|
44
71
|
```
|
|
45
72
|
|
|
46
73
|
Note that the only difference between this and the default **useState** hook is that you are not adding the initial value, cause you already did that when you created the store:
|
|
47
74
|
|
|
48
|
-
```
|
|
75
|
+
```ts
|
|
49
76
|
const countStore = new GlobalStore(0);
|
|
50
77
|
```
|
|
51
78
|
|
|
52
|
-
|
|
79
|
+
...
|
|
53
80
|
|
|
54
|
-
|
|
81
|
+
...
|
|
55
82
|
|
|
56
|
-
|
|
57
|
-
// The FIRST parameter is the initial value of the state
|
|
58
|
-
// The Second parameter is an API to restrict access to the state, will talk about that later on [README]:./README.advance.md
|
|
59
|
-
// The Third parameter is the key that will be used on the local-storage
|
|
60
|
-
const countStore = new GlobalStore(0, null, 'GLOBAL_COUNT');
|
|
61
|
-
```
|
|
83
|
+
# Persisting state into localhost
|
|
62
84
|
|
|
63
|
-
|
|
85
|
+
if you want to persist the value of the store into the. **localstorage**, you only have to add the property **localStorageKey** into the configuration parameter.
|
|
64
86
|
|
|
65
|
-
```
|
|
66
|
-
const
|
|
67
|
-
|
|
68
|
-
const [count, setCount] = useCountGlobal();
|
|
69
|
-
const onClickAddOne = () => setCount(count + 1);
|
|
87
|
+
```ts
|
|
88
|
+
const countStore = new GlobalStore(0, {
|
|
89
|
+
localStorageKey: 'my_persisted_state',
|
|
70
90
|
|
|
71
|
-
|
|
72
|
-
|
|
91
|
+
// by default, the state is encrypted to base64, but you can disable it, or use a custom encryptor
|
|
92
|
+
encrypt: false,
|
|
93
|
+
|
|
94
|
+
// by default, the state is encrypted to base64, but you can disable it, or use a custom decrypt
|
|
95
|
+
decrypt: false,
|
|
96
|
+
});
|
|
73
97
|
```
|
|
74
98
|
|
|
75
|
-
|
|
99
|
+
...
|
|
76
100
|
|
|
77
|
-
|
|
101
|
+
...
|
|
78
102
|
|
|
79
|
-
|
|
103
|
+
# Decoupled hook
|
|
80
104
|
|
|
105
|
+
If you want to access the global state outside a component or outside a hook, or without subscribing the component to the state changes...
|
|
81
106
|
|
|
82
|
-
|
|
83
|
-
|
|
107
|
+
This is especially useful when you want to create components that have edition access to a certain store, but they actually don't need to be reactive to the state changes, like a search component that just need to get the current state every time that is going to search the data; but actually don't need to be subscribed to the changes over the collection he is going to be filtering.
|
|
108
|
+
|
|
109
|
+
```ts
|
|
110
|
+
import { GlobalStore } from 'react-global-state-hooks';
|
|
84
111
|
|
|
85
112
|
const countStore = new GlobalStore(0);
|
|
86
113
|
|
|
@@ -88,47 +115,189 @@ const countStore = new GlobalStore(0);
|
|
|
88
115
|
export const useCountGlobal = countStore.getHook();
|
|
89
116
|
|
|
90
117
|
// this functions are not hooks, and they can be used in whatever place into your code, ClassComponents, OtherHooks, Services etc.
|
|
91
|
-
export const [
|
|
92
|
-
|
|
118
|
+
export const [getCount, sendCount] = countStore.getHookDecoupled();
|
|
93
119
|
```
|
|
94
120
|
|
|
95
|
-
Let's see a trivial example:
|
|
121
|
+
Let's see a trivial example:
|
|
122
|
+
|
|
123
|
+
...
|
|
96
124
|
|
|
97
125
|
```JSX
|
|
98
|
-
import { useCountGlobal,
|
|
126
|
+
import { useCountGlobal, sendCount } from './useCountGlobal'
|
|
99
127
|
|
|
100
128
|
const CountDisplayerComponent: React.FC = () => {
|
|
101
129
|
const [count] = useCountGlobal();
|
|
102
130
|
|
|
103
|
-
return (<
|
|
131
|
+
return (<Text>{count}<Text/>);
|
|
104
132
|
}
|
|
105
133
|
|
|
134
|
+
// here we have a separate component that is gonna handle the state of the previous component we created,
|
|
135
|
+
// this new component is not gonna be affected by the changes applied on <CountDisplayerComponent/>
|
|
106
136
|
// Stage2 does not need to be updated once the global count changes
|
|
107
137
|
const CountManagerComponent: React.FC = () => {
|
|
108
|
-
const increaseClick = () =>
|
|
109
|
-
const decreaseClick = () =>
|
|
138
|
+
const increaseClick = useCallback(() => sendCount(count => count + 1), []);
|
|
139
|
+
const decreaseClick = useCallback(() => sendCount(count => count - 1), []);
|
|
110
140
|
|
|
111
141
|
return (<>
|
|
112
|
-
<button
|
|
113
|
-
<button
|
|
142
|
+
<button onClick={increaseClick} >increase</button>
|
|
143
|
+
<button onClick={decreaseClick} >decrease</button>
|
|
114
144
|
</>);
|
|
115
145
|
}
|
|
116
146
|
```
|
|
117
147
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
148
|
+
...
|
|
149
|
+
|
|
150
|
+
...
|
|
151
|
+
|
|
152
|
+
# Restricting the manipulation of the global **state**
|
|
153
|
+
|
|
154
|
+
## Who hate reducers?
|
|
155
|
+
|
|
156
|
+
It's super common to have the wish or the necessity of restricting the manipulation of the **state** through a specific set of actions or manipulations...**Dispatches**? **Actions**? Let's make it simple BY adding a custom **API** to the configuration of our **GlobalStore**
|
|
157
|
+
...
|
|
158
|
+
|
|
159
|
+
```ts
|
|
160
|
+
const initialValue = 0;
|
|
161
|
+
|
|
162
|
+
const config = {
|
|
163
|
+
// this is not reactive information that you could also store in the async storage
|
|
164
|
+
// upating the metadata will not trigger the onStateChanged method or any update on the components
|
|
165
|
+
metadata: null,
|
|
166
|
+
|
|
167
|
+
// The lifecycle callbacks are: onInit, onStateChanged, onSubscribed and computePreventStateChange
|
|
168
|
+
};
|
|
169
|
+
|
|
170
|
+
const countStore = new GlobalStore(
|
|
171
|
+
initialValue,
|
|
172
|
+
config,
|
|
173
|
+
{
|
|
174
|
+
log: (message: string) => (): void => {
|
|
175
|
+
console.log(message);
|
|
176
|
+
},
|
|
177
|
+
|
|
178
|
+
increase(message: string) {
|
|
179
|
+
return (storeTools: StoreTools<number>) => {
|
|
180
|
+
this.log(message);
|
|
181
|
+
|
|
182
|
+
return storeTools.getState();
|
|
183
|
+
};
|
|
184
|
+
},
|
|
185
|
+
|
|
186
|
+
decrease(message: string) {
|
|
187
|
+
return (storeTools: StoreTools<number>) => {
|
|
188
|
+
this.log(message);
|
|
189
|
+
|
|
190
|
+
return storeTools.getState();
|
|
191
|
+
};
|
|
192
|
+
},
|
|
193
|
+
} as const // the -as const- is necessary to avoid typescript errors
|
|
194
|
+
);
|
|
195
|
+
|
|
196
|
+
// the way to get the hook is the same as for simple setters
|
|
197
|
+
const useCountStore = countStore.getHook();
|
|
198
|
+
|
|
199
|
+
// now instead of a setState method, you'll get an actions object
|
|
200
|
+
// that contains all the actions that you defined in the setterConfig
|
|
201
|
+
const [count, countActions] = useCountStore();
|
|
202
|
+
|
|
203
|
+
// count is the current state - 0 (number)
|
|
204
|
+
// countActions is an object that contains all the actions that you defined in the setterConfig
|
|
205
|
+
// countActions.increase(); // this will increase the count by 1, returns the new count (number)
|
|
206
|
+
// countActions.decrease(); // this will decrease the count by 1, returns the new count (number)
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
...
|
|
210
|
+
|
|
211
|
+
# Configuration callbacks
|
|
212
|
+
|
|
213
|
+
## config.onInit
|
|
214
|
+
|
|
215
|
+
This method will be called once the store is created after the constructor,
|
|
216
|
+
|
|
217
|
+
@examples
|
|
218
|
+
|
|
219
|
+
```ts
|
|
220
|
+
import { GlobalStore } from 'react-global-state-hooks';
|
|
221
|
+
|
|
222
|
+
const initialValue = 0;
|
|
223
|
+
|
|
224
|
+
const store = new GlobalStore(0, {
|
|
225
|
+
onInit: async ({ setMetadata, setState }) => {
|
|
226
|
+
const data = await someApiCall();
|
|
227
|
+
|
|
228
|
+
setState(data);
|
|
229
|
+
setMetadata({ isDataUpdated: true });
|
|
230
|
+
},
|
|
231
|
+
});
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
...
|
|
235
|
+
|
|
236
|
+
## config.onStateChanged
|
|
237
|
+
|
|
238
|
+
This method will be called every time the state is changed
|
|
239
|
+
|
|
240
|
+
@examples
|
|
241
|
+
|
|
242
|
+
```ts
|
|
243
|
+
import { GlobalStore } from 'react-global-state-hooks';
|
|
244
|
+
|
|
245
|
+
const store = new GlobalStore(0, {
|
|
246
|
+
onStateChanged: ({ getState }) => {
|
|
247
|
+
const state = getState();
|
|
248
|
+
|
|
249
|
+
console.log(state);
|
|
250
|
+
},
|
|
251
|
+
});
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
...
|
|
255
|
+
|
|
256
|
+
## config.onSubscribed
|
|
257
|
+
|
|
258
|
+
This method will be called every time a component is subscribed to the store
|
|
259
|
+
|
|
260
|
+
@examples
|
|
261
|
+
|
|
262
|
+
```ts
|
|
263
|
+
import { GlobalStore } from 'react-global-state-hooks';
|
|
264
|
+
|
|
265
|
+
const store = new GlobalStore(0, {
|
|
266
|
+
onSubscribed: ({ getState }) => {
|
|
267
|
+
console.log('A component was subscribed to the store');
|
|
268
|
+
},
|
|
269
|
+
});
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
...
|
|
273
|
+
|
|
274
|
+
## config.computePreventStateChange
|
|
275
|
+
|
|
276
|
+
This method will be called every time the state is going to be changed, if it returns true the state won't be changed
|
|
277
|
+
|
|
278
|
+
@examples
|
|
279
|
+
|
|
280
|
+
```ts
|
|
281
|
+
import { GlobalStore } from 'react-global-state-hooks';
|
|
282
|
+
|
|
283
|
+
const store = new GlobalStore(0, {
|
|
284
|
+
computePreventStateChange: ({ getState }) => {
|
|
285
|
+
const state = getState();
|
|
286
|
+
const shouldPrevent = state < 0;
|
|
287
|
+
|
|
288
|
+
if (shouldPrevent) return true;
|
|
289
|
+
|
|
290
|
+
return false;
|
|
291
|
+
},
|
|
292
|
+
});
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
...
|
|
121
296
|
|
|
122
|
-
|
|
123
|
-
1. Using REACT's simplest and default way to deal with the state.
|
|
124
|
-
2. Adding partial state designations (This is not on useState default functionality)
|
|
125
|
-
3. Added availability to create actions and decoupled access to the states, no more connects, and dispatches, just call your actions as a normal service of whatever other libraries.
|
|
126
|
-
4. This library is already taking care of avoiding re-renders if the new state does not have changes
|
|
127
|
-
5. This tool also take care for you to avoid **localStorage** data to lose the data types that you stored. For example when you are using datetimes
|
|
128
|
-
6. This library also is taking care of batching multiple stores updates by using **React unstable_batchedUpdates**; this is a problem that the **useState** have when you call multiple **setStates** into async flows as setTimeout
|
|
297
|
+
...
|
|
129
298
|
|
|
130
|
-
|
|
131
|
-
Are concern about performance? this library is for you, instead of handling huge complex stores with options like redux, or by passing the setState to a context Provider (because of the limitations that the context has)... You should just use this library, we are using the more atomic and 'native' way that REACT gives to handle the state, and that is the hook **useState**...
|
|
299
|
+
...
|
|
132
300
|
|
|
133
|
-
|
|
301
|
+
...
|
|
134
302
|
|
|
303
|
+
...
|
package/lib/GlobalStore.d.ts
CHANGED
|
@@ -1,55 +1,50 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
};
|
|
6
|
-
export declare const debounce: <T extends Function>(callback: T, wait?: number) => T;
|
|
7
|
-
/**
|
|
8
|
-
* This is a class to create global-store objects
|
|
9
|
-
* @template IState
|
|
10
|
-
* @param {IState} state - Initial state,
|
|
11
|
-
* @template IActions
|
|
12
|
-
* @param {IActions} actions - An specific api to restrict the use of the state,
|
|
13
|
-
* this will disable the default return of the state-setter of the hook, and instead will return the API
|
|
14
|
-
* @param {string} persistStoreAs - A name if you want to persist the state of the store in localstorage
|
|
15
|
-
* */
|
|
16
|
-
export declare class GlobalStore<IState, IActions extends IGlobalStore.IActionCollectionConfig<IState> | null = null> implements IGlobalStore.IGlobalState<IState, IActions> {
|
|
17
|
-
protected state: IState;
|
|
18
|
-
protected actions: IActions;
|
|
19
|
-
protected persistStoreAs: string | null;
|
|
20
|
-
protected subscribers: IGlobalStore.StateSetter<IState>[];
|
|
21
|
-
get isPersistStore(): boolean;
|
|
22
|
-
constructor(state: IState, actions?: IActions, persistStoreAs?: string | null);
|
|
23
|
-
private storedStateItem;
|
|
24
|
-
protected localStorageGetItem(): string | null;
|
|
25
|
-
protected getStoreItem(): IState;
|
|
26
|
-
protected localStorageSetItem(valueToStore: string): void;
|
|
27
|
-
protected setStoreItem(): void;
|
|
28
|
-
protected getPersistStoreValue: () => IState;
|
|
29
|
-
protected getStateCopy: () => IState;
|
|
1
|
+
export * from 'react-native-global-state-hooks';
|
|
2
|
+
import { GlobalStore as GlobalStoreBase } from 'react-native-global-state-hooks';
|
|
3
|
+
import { ActionCollectionConfig, GlobalStoreConfig, StateConfigCallbackParam, StateSetter } from './GlobalStore.types';
|
|
4
|
+
export declare class GlobalStore<TState, TMetadata = null, TStateSetter extends ActionCollectionConfig<TState, TMetadata> | StateSetter<TState> | null = StateSetter<TState>> extends GlobalStoreBase<TState, TMetadata, TStateSetter> {
|
|
30
5
|
/**
|
|
31
|
-
*
|
|
32
|
-
* @
|
|
6
|
+
* additional configuration for the store
|
|
7
|
+
* @template {TState} TState - The type of the state object
|
|
8
|
+
* @template {TMetadata} TMetadata - The type of the metadata object (optional) (default: null) no reactive information set to share with the subscribers
|
|
9
|
+
* @template {TStateSetter} TStateSetter - The type of the setterConfig object (optional) (default: null) if a configuration is passed, the hook will return an object with the actions then all the store manipulation will be done through the actions
|
|
10
|
+
* @property {GlobalStoreConfig<TState, TMetadata, TStateSetter>} config.metadata - The metadata to pass to the callbacks (optional) (default: null)
|
|
11
|
+
* @property {GlobalStoreConfig<TState, TMetadata, TStateSetter>} config.onInit - The callback to execute when the store is initialized (optional) (default: null)
|
|
12
|
+
* @property {GlobalStoreConfig<TState, TMetadata, TStateSetter>} config.onStateChanged - The callback to execute when the state is changed (optional) (default: null)
|
|
13
|
+
* @property {GlobalStoreConfig<TState, TMetadata, TStateSetter>} config.onSubscribed - The callback to execute when a component is subscribed to the store (optional) (default: null)
|
|
14
|
+
* @property {GlobalStoreConfig<TState, TMetadata, TStateSetter>} config.computePreventStateChange - The callback to execute when the state is changed to compute if the state change should be prevented (optional) (default: null)
|
|
15
|
+
* @property {GlobalStoreConfig<TState, TMetadata, TStateSetter>} config.localStorageKey - The key to use to store the state in the localStorage (optional) (default: null) if not null the state will be stored in the localStorage
|
|
33
16
|
*/
|
|
34
|
-
|
|
17
|
+
protected config: GlobalStoreConfig<TState, TMetadata, TStateSetter>;
|
|
35
18
|
/**
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
* @
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
19
|
+
* Create a new instance of the GlobalStore
|
|
20
|
+
* @param {TState} state - The initial state
|
|
21
|
+
* @param {TStateSetter} setterConfig - The actions configuration object (optional) (default: null) if not null the store manipulation will be done through the actions
|
|
22
|
+
* @param {GlobalStoreConfig<TState, TMetadata>} config - The configuration object (optional) (default: { metadata: null })
|
|
23
|
+
* @param {StateConfigCallbackParam<TState, TMetadata>} config.metadata - The metadata to pass to the callbacks (optional) (default: null)
|
|
24
|
+
* @param {StateConfigCallbackParam<TState, TMetadata>} config.onInit - The callback to execute when the store is initialized (optional) (default: null)
|
|
25
|
+
* @param {StateConfigCallbackParam<TState, TMetadata>} config.onStateChanged - The callback to execute when the state is changed (optional) (default: null)
|
|
26
|
+
* @param {StateConfigCallbackParam<TState, TMetadata>} config.onSubscribed - The callback to execute when a subscriber is added (optional) (default: null)
|
|
27
|
+
* @param {StateConfigCallbackParam<TState, TMetadata>} config.computePreventStateChange - The callback to execute when the state is changed to compute if the state change should be prevented (optional) (default: null)
|
|
28
|
+
* @param {StateConfigCallbackParam<TState, TMetadata>} config.localStorageKey - The key to use to store the state in the localStorage (optional) (default: null) if not null the state will be stored in the localStorage
|
|
29
|
+
* */
|
|
30
|
+
constructor(state: TState, { onInit: onInitConfig, ...config }?: GlobalStoreConfig<TState, TMetadata, TStateSetter>, setterConfig?: TStateSetter | null);
|
|
31
|
+
protected setLocalStorageValue: () => void;
|
|
32
|
+
protected getLocalStorageValue: () => string;
|
|
43
33
|
/**
|
|
44
|
-
|
|
34
|
+
* This method will be called once the store is created after the constructor,
|
|
35
|
+
* this method is different from the onInit of the confg property and it won't be overriden
|
|
45
36
|
*/
|
|
46
|
-
protected
|
|
47
|
-
protected
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
37
|
+
protected onInit: ({ setState, }: StateConfigCallbackParam<TState, TMetadata, TStateSetter>) => Promise<void>;
|
|
38
|
+
protected onStateChanged: () => void;
|
|
39
|
+
/**
|
|
40
|
+
* set the state and update all the subscribers,
|
|
41
|
+
* In react web ReacDom allows to batch the state updates, this method will use the unstable_batchedUpdates method if it exists
|
|
42
|
+
* @param {StateSetter<TState>} setter - The setter function or the value to set
|
|
43
|
+
* @param {React.Dispatch<React.SetStateAction<TState>>} invokerSetState - The setState function of the component that invoked the state change (optional) (default: null) this is used to updated first the component that invoked the state change
|
|
44
|
+
* */
|
|
45
|
+
protected setState: ({ invokerSetState, state, }: {
|
|
46
|
+
state: TState;
|
|
47
|
+
invokerSetState?: React.Dispatch<React.SetStateAction<TState>>;
|
|
48
|
+
}) => void;
|
|
53
49
|
}
|
|
54
|
-
export default GlobalStore;
|
|
55
50
|
//# sourceMappingURL=GlobalStore.d.ts.map
|
package/lib/GlobalStore.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GlobalStore.d.ts","sourceRoot":"","sources":["../src/GlobalStore.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"GlobalStore.d.ts","sourceRoot":"","sources":["../src/GlobalStore.ts"],"names":[],"mappings":"AAEA,cAAc,iCAAiC,CAAC;AAEhD,OAAO,EAGL,WAAW,IAAI,eAAe,EAC/B,MAAM,iCAAiC,CAAC;AAEzC,OAAO,EACL,sBAAsB,EACtB,iBAAiB,EACjB,wBAAwB,EACxB,WAAW,EACZ,MAAM,qBAAqB,CAAC;AAE7B,qBAAa,WAAW,CACtB,MAAM,EACN,SAAS,GAAG,IAAI,EAChB,YAAY,SACR,sBAAsB,CAAC,MAAM,EAAE,SAAS,CAAC,GACzC,WAAW,CAAC,MAAM,CAAC,GACnB,IAAI,GAAG,WAAW,CAAC,MAAM,CAAC,CAC9B,SAAQ,eAAe,CAAC,MAAM,EAAE,SAAS,EAAE,YAAY,CAAC;IACxD;;;;;;;;;;;OAWG;IACH,SAAS,CAAC,MAAM,EAAE,iBAAiB,CAAC,MAAM,EAAE,SAAS,EAAE,YAAY,CAAC,CAAC;IAErE;;;;;;;;;;;SAWK;gBAEH,KAAK,EAAE,MAAM,EACb,EACE,MAAM,EAAE,YAAY,EACpB,GAAG,MAAM,EACV,GAAE,iBAAiB,CAAC,MAAM,EAAE,SAAS,EAAE,YAAY,CAAM,EAC1D,YAAY,GAAE,YAAY,GAAG,IAAW;IAwB1C,SAAS,CAAC,oBAAoB,aAqB5B;IAEF,SAAS,CAAC,oBAAoB,eAmB5B;IAEF;;;OAGG;IACH,SAAS,CAAC,MAAM,kBAEb,yBAAyB,MAAM,EAAE,SAAS,EAAE,YAAY,CAAC,mBAgB1D;IAEF,SAAS,CAAC,cAAc,aAEtB;IAEF;;;;;SAKK;IACL,SAAS,CAAC,QAAQ;eAIT,MAAM;0BACK,MAAM,QAAQ,CAAC,MAAM,cAAc,CAAC,MAAM,CAAC,CAAC;eAoB9D;CACH"}
|
package/lib/GlobalStore.js
CHANGED
|
@@ -1,170 +1,101 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.GlobalStore =
|
|
3
|
+
exports.GlobalStore = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
const react_dom_1 = tslib_1.__importDefault(require("react-dom"));
|
|
6
|
-
|
|
7
|
-
const
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
}
|
|
52
|
-
return
|
|
53
|
-
valueWrapper,
|
|
54
|
-
this.stateOrchestrator,
|
|
55
|
-
];
|
|
6
|
+
tslib_1.__exportStar(require("react-native-global-state-hooks"), exports);
|
|
7
|
+
const react_native_global_state_hooks_1 = require("react-native-global-state-hooks");
|
|
8
|
+
class GlobalStore extends react_native_global_state_hooks_1.GlobalStore {
|
|
9
|
+
/**
|
|
10
|
+
* Create a new instance of the GlobalStore
|
|
11
|
+
* @param {TState} state - The initial state
|
|
12
|
+
* @param {TStateSetter} setterConfig - The actions configuration object (optional) (default: null) if not null the store manipulation will be done through the actions
|
|
13
|
+
* @param {GlobalStoreConfig<TState, TMetadata>} config - The configuration object (optional) (default: { metadata: null })
|
|
14
|
+
* @param {StateConfigCallbackParam<TState, TMetadata>} config.metadata - The metadata to pass to the callbacks (optional) (default: null)
|
|
15
|
+
* @param {StateConfigCallbackParam<TState, TMetadata>} config.onInit - The callback to execute when the store is initialized (optional) (default: null)
|
|
16
|
+
* @param {StateConfigCallbackParam<TState, TMetadata>} config.onStateChanged - The callback to execute when the state is changed (optional) (default: null)
|
|
17
|
+
* @param {StateConfigCallbackParam<TState, TMetadata>} config.onSubscribed - The callback to execute when a subscriber is added (optional) (default: null)
|
|
18
|
+
* @param {StateConfigCallbackParam<TState, TMetadata>} config.computePreventStateChange - The callback to execute when the state is changed to compute if the state change should be prevented (optional) (default: null)
|
|
19
|
+
* @param {StateConfigCallbackParam<TState, TMetadata>} config.localStorageKey - The key to use to store the state in the localStorage (optional) (default: null) if not null the state will be stored in the localStorage
|
|
20
|
+
* */
|
|
21
|
+
constructor(state, _a = {}, setterConfig) {
|
|
22
|
+
var _b;
|
|
23
|
+
var { onInit: onInitConfig } = _a, config = tslib_1.__rest(_a, ["onInit"]);
|
|
24
|
+
if (setterConfig === void 0) { setterConfig = null; }
|
|
25
|
+
debugger;
|
|
26
|
+
const decrypt = (config === null || config === void 0 ? void 0 : config.decrypt) === undefined ? (_b = config === null || config === void 0 ? void 0 : config.encrypt) !== null && _b !== void 0 ? _b : true : config === null || config === void 0 ? void 0 : config.decrypt;
|
|
27
|
+
super(state, Object.assign({ metadata: null, encrypt: true, decrypt }, (config !== null && config !== void 0 ? config : {})), setterConfig);
|
|
28
|
+
this.setLocalStorageValue = () => {
|
|
29
|
+
const { localStorageKey } = this.config;
|
|
30
|
+
debugger;
|
|
31
|
+
let stateToStore = (0, react_native_global_state_hooks_1.formatToStore)(this.getStateClone(), {
|
|
32
|
+
stringify: true,
|
|
33
|
+
});
|
|
34
|
+
const { encrypt } = this.config;
|
|
35
|
+
if (encrypt) {
|
|
36
|
+
const isEncryptCallback = typeof encrypt === 'function';
|
|
37
|
+
const encryptCallback = (isEncryptCallback ? encrypt : (value) => btoa(value));
|
|
38
|
+
stateToStore = encryptCallback(stateToStore);
|
|
39
|
+
}
|
|
40
|
+
localStorage.setItem(localStorageKey, stateToStore);
|
|
41
|
+
};
|
|
42
|
+
this.getLocalStorageValue = () => {
|
|
43
|
+
const { localStorageKey } = this.config;
|
|
44
|
+
debugger;
|
|
45
|
+
let storedState = localStorage.getItem(localStorageKey);
|
|
46
|
+
const { decrypt } = this.config;
|
|
47
|
+
if (decrypt) {
|
|
48
|
+
const isDecryptCallback = typeof decrypt === 'function';
|
|
49
|
+
const decryptCallback = (isDecryptCallback ? decrypt : (value) => atob(value));
|
|
50
|
+
storedState = decryptCallback(storedState);
|
|
51
|
+
}
|
|
52
|
+
return storedState;
|
|
56
53
|
};
|
|
57
54
|
/**
|
|
58
|
-
* This
|
|
59
|
-
*
|
|
60
|
-
* @return [currentState, GlobalState.IHookResult<IState, IActions, IApi>]
|
|
55
|
+
* This method will be called once the store is created after the constructor,
|
|
56
|
+
* this method is different from the onInit of the confg property and it won't be overriden
|
|
61
57
|
*/
|
|
62
|
-
this.
|
|
63
|
-
const
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
58
|
+
this.onInit = ({ setState, }) => tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
59
|
+
const { localStorageKey } = this.config;
|
|
60
|
+
if (!localStorageKey)
|
|
61
|
+
return;
|
|
62
|
+
const storedState = this.getLocalStorageValue();
|
|
63
|
+
if (storedState === null) {
|
|
64
|
+
this.setLocalStorageValue();
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
const jsonParsed = JSON.parse(storedState);
|
|
68
|
+
const state = (0, react_native_global_state_hooks_1.formatFromStore)(jsonParsed);
|
|
69
|
+
setState(state);
|
|
70
|
+
});
|
|
71
|
+
this.onStateChanged = () => {
|
|
72
|
+
this.setLocalStorageValue();
|
|
68
73
|
};
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
74
|
+
/**
|
|
75
|
+
* set the state and update all the subscribers,
|
|
76
|
+
* In react web ReacDom allows to batch the state updates, this method will use the unstable_batchedUpdates method if it exists
|
|
77
|
+
* @param {StateSetter<TState>} setter - The setter function or the value to set
|
|
78
|
+
* @param {React.Dispatch<React.SetStateAction<TState>>} invokerSetState - The setState function of the component that invoked the state change (optional) (default: null) this is used to updated first the component that invoked the state change
|
|
79
|
+
* */
|
|
80
|
+
this.setState = ({ invokerSetState, state, }) => {
|
|
81
|
+
// update the state
|
|
82
|
+
this.state = state;
|
|
83
|
+
const unstable_batchedUpdates = react_dom_1.default.unstable_batchedUpdates ||
|
|
84
|
+
((callback) => callback());
|
|
85
|
+
unstable_batchedUpdates(() => {
|
|
86
|
+
// execute first the callback of the component that invoked the state change
|
|
87
|
+
invokerSetState === null || invokerSetState === void 0 ? void 0 : invokerSetState(state);
|
|
88
|
+
// update all the subscribers
|
|
89
|
+
this.subscribers.forEach((setState) => {
|
|
90
|
+
if (setState === invokerSetState)
|
|
91
|
+
return;
|
|
92
|
+
setState(state);
|
|
93
|
+
});
|
|
84
94
|
});
|
|
85
|
-
this.state = newState;
|
|
86
|
-
// batch store updates
|
|
87
|
-
GlobalStore.batchedUpdates.push([() => this.subscribers.forEach((updateChild) => updateChild(newState)), this, newState]);
|
|
88
|
-
GlobalStore.ExecutePendingBatchesCallbacks.push(callback);
|
|
89
|
-
GlobalStore.ExecutePendingBatches();
|
|
90
95
|
};
|
|
91
|
-
|
|
92
|
-
this.
|
|
93
|
-
|
|
94
|
-
this.setStoreItem();
|
|
95
|
-
});
|
|
96
|
-
this.getActions = () => {
|
|
97
|
-
const actions = this.actions;
|
|
98
|
-
// Setter is allways async because of the render batch
|
|
99
|
-
const setter = this.isPersistStore ? this.globalSetterToPersistStoreAsync : this.globalSetterAsync;
|
|
100
|
-
return Object.keys(actions).reduce((accumulator, key) => (Object.assign(Object.assign({}, accumulator), { [key]: (...parameres) => tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
101
|
-
let promise;
|
|
102
|
-
const setterWrapper = (value) => {
|
|
103
|
-
promise = setter(value);
|
|
104
|
-
return promise;
|
|
105
|
-
};
|
|
106
|
-
const result = actions[key](...parameres)(setterWrapper, this.getStateCopy());
|
|
107
|
-
const resultPromise = Promise.resolve(result) === result ? result : Promise.resolve();
|
|
108
|
-
yield Promise.all([promise, resultPromise]);
|
|
109
|
-
return result;
|
|
110
|
-
}) })), {});
|
|
111
|
-
};
|
|
112
|
-
}
|
|
113
|
-
localStorageGetItem() {
|
|
114
|
-
return localStorage.getItem(this.persistStoreAs);
|
|
115
|
-
}
|
|
116
|
-
getStoreItem() {
|
|
117
|
-
if (this.storedStateItem !== undefined)
|
|
118
|
-
return this.storedStateItem;
|
|
119
|
-
const item = this.localStorageGetItem();
|
|
120
|
-
if (item) {
|
|
121
|
-
const value = JSON.parse(item);
|
|
122
|
-
const newState = (0, json_storage_formatter_1.formatFromStore)(value);
|
|
123
|
-
this.state = newState;
|
|
124
|
-
}
|
|
125
|
-
return this.state;
|
|
126
|
-
}
|
|
127
|
-
localStorageSetItem(valueToStore) {
|
|
128
|
-
localStorage.setItem(this.persistStoreAs, valueToStore);
|
|
129
|
-
}
|
|
130
|
-
setStoreItem() {
|
|
131
|
-
if (this.storedStateItem === this.state)
|
|
132
|
-
return;
|
|
133
|
-
this.storedStateItem = this.state;
|
|
134
|
-
const valueToStore = (0, json_storage_formatter_1.formatToStore)(this.state);
|
|
135
|
-
this.localStorageSetItem(JSON.stringify(valueToStore));
|
|
136
|
-
}
|
|
137
|
-
get stateOrchestrator() {
|
|
138
|
-
if (this._stateOrchestrator)
|
|
139
|
-
return this._stateOrchestrator;
|
|
140
|
-
if (this.actions) {
|
|
141
|
-
this._stateOrchestrator = this.getActions();
|
|
142
|
-
}
|
|
143
|
-
else if (this.persistStoreAs) {
|
|
144
|
-
this._stateOrchestrator = this.globalSetterToPersistStoreAsync;
|
|
145
|
-
}
|
|
146
|
-
else {
|
|
147
|
-
this._stateOrchestrator = this.globalSetterAsync;
|
|
148
|
-
}
|
|
149
|
-
return this._stateOrchestrator;
|
|
96
|
+
const parameters = this.getConfigCallbackParam({});
|
|
97
|
+
this.onInit(parameters);
|
|
98
|
+
onInitConfig === null || onInitConfig === void 0 ? void 0 : onInitConfig(parameters);
|
|
150
99
|
}
|
|
151
100
|
}
|
|
152
101
|
exports.GlobalStore = GlobalStore;
|
|
153
|
-
/**
|
|
154
|
-
** [subscriber-update-callback, hook, newState]
|
|
155
|
-
*/
|
|
156
|
-
GlobalStore.batchedUpdates = [];
|
|
157
|
-
GlobalStore.ExecutePendingBatchesCallbacks = [];
|
|
158
|
-
// avoid multiples calls to batchedUpdates
|
|
159
|
-
GlobalStore.ExecutePendingBatches = (0, exports.debounce)(() => {
|
|
160
|
-
const reactBatchedUpdates = react_dom_1.default.unstable_batchedUpdates || ((mock) => mock());
|
|
161
|
-
reactBatchedUpdates(() => {
|
|
162
|
-
GlobalStore.batchedUpdates.forEach(([execute]) => {
|
|
163
|
-
execute();
|
|
164
|
-
});
|
|
165
|
-
GlobalStore.batchedUpdates = [];
|
|
166
|
-
GlobalStore.ExecutePendingBatchesCallbacks.forEach((callback) => callback());
|
|
167
|
-
GlobalStore.ExecutePendingBatchesCallbacks = [];
|
|
168
|
-
});
|
|
169
|
-
}, 0);
|
|
170
|
-
exports.default = GlobalStore;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import * as TGlobalStoreBase from 'react-native-global-state-hooks/lib/GlobalStore.types';
|
|
2
|
+
export type StateSetter<TState> = TGlobalStoreBase.StateSetter<TState>;
|
|
3
|
+
export type StateChanges<TState> = TGlobalStoreBase.StateChanges<TState>;
|
|
4
|
+
export type StoreTools<TState, TMetadata = null> = TGlobalStoreBase.StoreTools<TState, TMetadata>;
|
|
5
|
+
export interface ActionCollectionConfig<TState, TMetadata> extends TGlobalStoreBase.ActionCollectionConfig<TState, TMetadata> {
|
|
6
|
+
}
|
|
7
|
+
export type ActionCollectionResult<TState, TMetadata, TStateSetter extends ActionCollectionConfig<TState, TMetadata> | StateSetter<TState> = StateSetter<TState>> = TGlobalStoreBase.ActionCollectionResult<TState, TMetadata, TStateSetter>;
|
|
8
|
+
export type StateConfigCallbackParam<TState, TMetadata, TStateSetter extends ActionCollectionConfig<TState, TMetadata> | StateSetter<TState> = StateSetter<TState>> = TGlobalStoreBase.StateConfigCallbackParam<TState, TMetadata, TStateSetter>;
|
|
9
|
+
export type StateChangesParam<TState, TMetadata, TStateSetter extends ActionCollectionConfig<TState, TMetadata> | StateSetter<TState> = StateSetter<TState>> = TGlobalStoreBase.StateChangesParam<TState, TMetadata, TStateSetter>;
|
|
10
|
+
/**
|
|
11
|
+
* Configuration of the store (optional) - if you don't need to use the store configuration you don't need to pass this parameter
|
|
12
|
+
* @param {StateConfigCallbackParam<TState, TMetadata> => void} onInit - callback function called when the store is initialized
|
|
13
|
+
* @param {StateConfigCallbackParam<TState, TMetadata> => void} onSubscribed - callback function called every time a component is subscribed to the store
|
|
14
|
+
* @param {StateChangesParam<TState, TMetadata> => boolean} computePreventStateChange - callback function called every time the state is changed and it allows you to prevent the state change
|
|
15
|
+
* @param {StateChangesParam<TState, TMetadata> => void} onStateChanged - callback function called every time the state is changed
|
|
16
|
+
* @template TState - the type of the state
|
|
17
|
+
* @template TMetadata - the type of the metadata (optional) - if you don't pass an metadata as a parameter, you can pass null
|
|
18
|
+
* @template {ActionCollectionConfig<TState,TMetadata> | null} TStateSetter - the configuration of the API (optional) - if you don't pass an API as a parameter, you can pass null
|
|
19
|
+
* */
|
|
20
|
+
export type GlobalStoreConfig<TState, TMetadata, TStateSetter extends TGlobalStoreBase.ActionCollectionConfig<TState, TMetadata> | TGlobalStoreBase.StateSetter<TState> = TGlobalStoreBase.StateSetter<TState>> = TGlobalStoreBase.GlobalStoreConfig<TState, TMetadata, TStateSetter> & {
|
|
21
|
+
localStorageKey?: string;
|
|
22
|
+
encrypt?: boolean | ((value: string) => string);
|
|
23
|
+
decrypt?: boolean | ((value: string) => string);
|
|
24
|
+
};
|
|
25
|
+
//# sourceMappingURL=GlobalStore.types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GlobalStore.types.d.ts","sourceRoot":"","sources":["../src/GlobalStore.types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,gBAAgB,MAAM,uDAAuD,CAAC;AAE1F,MAAM,MAAM,WAAW,CAAC,MAAM,IAAI,gBAAgB,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;AAEvE,MAAM,MAAM,YAAY,CAAC,MAAM,IAAI,gBAAgB,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC;AAEzE,MAAM,MAAM,UAAU,CAAC,MAAM,EAAE,SAAS,GAAG,IAAI,IAAI,gBAAgB,CAAC,UAAU,CAC5E,MAAM,EACN,SAAS,CACV,CAAC;AAEF,MAAM,WAAW,sBAAsB,CAAC,MAAM,EAAE,SAAS,CACvD,SAAQ,gBAAgB,CAAC,sBAAsB,CAAC,MAAM,EAAE,SAAS,CAAC;CAAG;AAEvE,MAAM,MAAM,sBAAsB,CAChC,MAAM,EACN,SAAS,EACT,YAAY,SACR,sBAAsB,CAAC,MAAM,EAAE,SAAS,CAAC,GACzC,WAAW,CAAC,MAAM,CAAC,GAAG,WAAW,CAAC,MAAM,CAAC,IAC3C,gBAAgB,CAAC,sBAAsB,CAAC,MAAM,EAAE,SAAS,EAAE,YAAY,CAAC,CAAC;AAE7E,MAAM,MAAM,wBAAwB,CAClC,MAAM,EACN,SAAS,EACT,YAAY,SACR,sBAAsB,CAAC,MAAM,EAAE,SAAS,CAAC,GACzC,WAAW,CAAC,MAAM,CAAC,GAAG,WAAW,CAAC,MAAM,CAAC,IAC3C,gBAAgB,CAAC,wBAAwB,CAAC,MAAM,EAAE,SAAS,EAAE,YAAY,CAAC,CAAC;AAE/E,MAAM,MAAM,iBAAiB,CAC3B,MAAM,EACN,SAAS,EACT,YAAY,SACR,sBAAsB,CAAC,MAAM,EAAE,SAAS,CAAC,GACzC,WAAW,CAAC,MAAM,CAAC,GAAG,WAAW,CAAC,MAAM,CAAC,IAC3C,gBAAgB,CAAC,iBAAiB,CAAC,MAAM,EAAE,SAAS,EAAE,YAAY,CAAC,CAAC;AAExE;;;;;;;;;KASK;AACL,MAAM,MAAM,iBAAiB,CAC3B,MAAM,EACN,SAAS,EACT,YAAY,SACR,gBAAgB,CAAC,sBAAsB,CAAC,MAAM,EAAE,SAAS,CAAC,GAC1D,gBAAgB,CAAC,WAAW,CAAC,MAAM,CAAC,GAAG,gBAAgB,CAAC,WAAW,CAAC,MAAM,CAAC,IAC7E,gBAAgB,CAAC,iBAAiB,CAAC,MAAM,EAAE,SAAS,EAAE,YAAY,CAAC,GAAG;IACxE,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,OAAO,CAAC,EAAE,OAAO,GAAG,CAAC,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC,CAAC;IAChD,OAAO,CAAC,EAAE,OAAO,GAAG,CAAC,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC,CAAC;CACjD,CAAC"}
|
|
File without changes
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-global-state-hooks",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.15",
|
|
4
4
|
"description": "This is a package to easily handling global-state across your react components No-redux, No-context.",
|
|
5
5
|
"main": "lib/GlobalStore.js",
|
|
6
6
|
"files": [
|
|
@@ -60,6 +60,6 @@
|
|
|
60
60
|
"react-dom": "workspace:*"
|
|
61
61
|
},
|
|
62
62
|
"dependencies": {
|
|
63
|
-
"
|
|
63
|
+
"react-native-global-state-hooks": "^2.1.9"
|
|
64
64
|
}
|
|
65
65
|
}
|
package/README.advance.md
DELETED
|
@@ -1,123 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
## Creating hooks with reusable actions
|
|
3
|
-
|
|
4
|
-
Let's say you want to have a STATE with a specific set of actions that you could be reused. With this library is pretty easy to accomplish. Let's create **increase** and **decrease** actions to our count-store. **useCountGlobal.ts**:
|
|
5
|
-
|
|
6
|
-
```JSX
|
|
7
|
-
import {
|
|
8
|
-
IActionCollectionConfig,
|
|
9
|
-
IActionCollectionResult,
|
|
10
|
-
StateSetter,
|
|
11
|
-
} from 'react-global-state-hooks/lib/GlobalStoreTypes';
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* When using a custom api, the getHook and getHookDecoupled will not longer return directly the setter,
|
|
15
|
-
* intead they will return and api with the specific actions and mutations defined for the store
|
|
16
|
-
* Creating a configuration object for our api
|
|
17
|
-
*/
|
|
18
|
-
const countActionsApi: IActionCollectionConfig<number> = {
|
|
19
|
-
/* Decrease the value of the count */
|
|
20
|
-
decrease(decrease: number) {
|
|
21
|
-
/**
|
|
22
|
-
* We need to return the async function that is gonna take care of the state mutation or actions
|
|
23
|
-
*/
|
|
24
|
-
return async (setter: StateSetter<number>, state: number) => {
|
|
25
|
-
/**
|
|
26
|
-
* Next, we perfom whatever modification we want on top of the store
|
|
27
|
-
*/
|
|
28
|
-
return setter(state - decrease);
|
|
29
|
-
};
|
|
30
|
-
},
|
|
31
|
-
|
|
32
|
-
//* Lets add a new action to increase the value of the count */
|
|
33
|
-
increase(increase: number) {
|
|
34
|
-
|
|
35
|
-
return async (setter: StateSetter<number>, state: number) => {
|
|
36
|
-
return setter(state + increase);
|
|
37
|
-
};
|
|
38
|
-
},
|
|
39
|
-
};
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* Now our getHook and getHookDecoupled are gonna return our custom api instead of the StateSetter,
|
|
43
|
-
* This will allow us to have more control over our store since the mutations of the same are gonna be limitated
|
|
44
|
-
*/
|
|
45
|
-
const countStore = new GlobalStore(0, countActionsApi);
|
|
46
|
-
```
|
|
47
|
-
|
|
48
|
-
If we remove all the explanatory comments the code will look like this:
|
|
49
|
-
|
|
50
|
-
```TS
|
|
51
|
-
const countStore = new GlobalStore(0, {
|
|
52
|
-
decrease(decrease: number) {
|
|
53
|
-
return (setter: StateSetter<number>, state: number) =>
|
|
54
|
-
setter(state - decrease);
|
|
55
|
-
},
|
|
56
|
-
|
|
57
|
-
increase(increase: number) {
|
|
58
|
-
return (setter: StateSetter<number>, state: number) =>
|
|
59
|
-
setter(state + increase);
|
|
60
|
-
},
|
|
61
|
-
} as IActionCollectionConfig<number>);
|
|
62
|
-
```
|
|
63
|
-
|
|
64
|
-
Now lets get our new global hook with specific API
|
|
65
|
-
|
|
66
|
-
```TS
|
|
67
|
-
export interface ICountActions
|
|
68
|
-
extends IActionCollectionResult<number, IActionCollectionConfig<number>> {
|
|
69
|
-
decrease: (decrease: number) => Promise<number>;
|
|
70
|
-
increase: (increase: number) => Promise<number>;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
/**
|
|
74
|
-
* The ICountActions interface is optional but it allow you yo get more accurate results for the typescript autocompletes and validations, ignore this if you are not using TS
|
|
75
|
-
*/
|
|
76
|
-
export const useCountGlobal = countStore.getHook<ICountActions>();
|
|
77
|
-
```
|
|
78
|
-
|
|
79
|
-
And that's it! the result of our useCountGlobal will return our actions instead of a simple setter... Let's see how that will look:
|
|
80
|
-
|
|
81
|
-
```JSX
|
|
82
|
-
import { useCountGlobal } from './useCountGlobal'
|
|
83
|
-
|
|
84
|
-
const MyComponent: Reac.FC = () => {
|
|
85
|
-
const [count, countActions] = useCountGlobal();
|
|
86
|
-
|
|
87
|
-
// this functions are strongly typed
|
|
88
|
-
const increaseClick = () => countActions.increase(1);
|
|
89
|
-
const decreaseClick = () => countActions.decrease(1);
|
|
90
|
-
|
|
91
|
-
return (<>
|
|
92
|
-
<label>{count}<label/><br/>
|
|
93
|
-
<button onPress={increaseClick}>increase<button/>
|
|
94
|
-
<button onPress={decreaseClick}>decrease<button/>
|
|
95
|
-
</>);
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
```
|
|
99
|
-
|
|
100
|
-
## Customize persist storage
|
|
101
|
-
|
|
102
|
-
Let suppose you don't like **async-storage** or you also want to implement some kind of encrypt-process. You could easily extend the **GlobalStore** Class, and customize your persist store implementation.
|
|
103
|
-
|
|
104
|
-
```JSX
|
|
105
|
-
import GlobalState from 'react-global-state-hooks';
|
|
106
|
-
import { IActionCollection } from 'react-global-state-hooks/lib/GlobalStoreTypes';
|
|
107
|
-
|
|
108
|
-
export class SecureGlobalState<
|
|
109
|
-
IState,
|
|
110
|
-
IPersist extends string | null = null,
|
|
111
|
-
IsPersist extends boolean = IPersist extends null ? false : true,
|
|
112
|
-
IActions extends IActionCollection<IState> | null = null
|
|
113
|
-
> extends GlobalState<IState, IPersist, IsPersist, IActions> {
|
|
114
|
-
|
|
115
|
-
protected getStoreItem = () => secureStorage.getItem(this.persistStoreAs as string);
|
|
116
|
-
|
|
117
|
-
/** value is a json string*/
|
|
118
|
-
protected setStoreItem = (value: string) => secureStorage.setItem(this.persistStoreAs as string, value);
|
|
119
|
-
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
export default SecureGlobalState;
|
|
123
|
-
```
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @param {StateSetter<IState>} setter - add a new value to the state
|
|
3
|
-
* @returns {Promise<void>} result - resolves when update_batches finished
|
|
4
|
-
*/
|
|
5
|
-
export type StateSetter<IState> = (setter: Partial<IState> | ((state: IState) => Partial<IState>)) => Promise<void>;
|
|
6
|
-
/**
|
|
7
|
-
* This is the structure required by the API actions in order to be able to capture action parameters and inject state setter into actions.
|
|
8
|
-
*/
|
|
9
|
-
export type IAction<IState> = <IResult>(...params: any[]) => (setter: StateSetter<IState>, currentState: IState) => Promise<unknown> | IResult;
|
|
10
|
-
/**
|
|
11
|
-
* Configuration of you API
|
|
12
|
-
*/
|
|
13
|
-
export interface IActionCollectionConfig<IState> {
|
|
14
|
-
[key: string]: IAction<IState>;
|
|
15
|
-
}
|
|
16
|
-
/**
|
|
17
|
-
* This is the API result of the hook (if you passed an API as a parameter)
|
|
18
|
-
*/
|
|
19
|
-
export type IActionCollectionResult<IState, IActions extends IActionCollectionConfig<IState> | null> = {
|
|
20
|
-
[key in keyof IActions]: (...params: any[]) => unknown;
|
|
21
|
-
};
|
|
22
|
-
/**
|
|
23
|
-
* Hook result, if you passed an API as a parameter it will be returned in the second position of the hook invoke.
|
|
24
|
-
*/
|
|
25
|
-
export type IHookResult<IState, IActions extends IActionCollectionConfig<IState> | null = null, IApi extends IActionCollectionResult<IState, IActions> | null = IActions extends null ? null : IActionCollectionResult<IState, IActions>> = IApi extends null ? StateSetter<IState> : IActions extends IActionCollectionConfig<IState> ? IApi extends IActionCollectionResult<IState, IActions> ? IApi : StateSetter<IState> : StateSetter<IState>;
|
|
26
|
-
/**
|
|
27
|
-
* This is a class to create global-store objects
|
|
28
|
-
* @template IState
|
|
29
|
-
* @param {IState} state - Initial state,
|
|
30
|
-
* @template IActions
|
|
31
|
-
* @param {IActions} actions - An specific api to restrict the use of the state,
|
|
32
|
-
* this will disable the default return of the state-setter of the hook, and instead will return the API
|
|
33
|
-
* @param {string} persistStoreAs - A name if you want to persist the state of the store in localstorage
|
|
34
|
-
* */
|
|
35
|
-
export interface IGlobalState<IState, IActions extends IActionCollectionConfig<IState> | null = null> {
|
|
36
|
-
/**
|
|
37
|
-
* Returns a global hook that will share information across components by subscribing them to a specific store.
|
|
38
|
-
* @return [currentState, GlobalState.IHookResult<IState, IActions, IApi>]
|
|
39
|
-
*/
|
|
40
|
-
getHook: <IApi extends IActions extends IActionCollectionResult<IState, IActions> ? IActionCollectionResult<IState, IActions> : null>() => () => [
|
|
41
|
-
IState,
|
|
42
|
-
IHookResult<IState, IActions, IApi>
|
|
43
|
-
];
|
|
44
|
-
/**
|
|
45
|
-
* This is an access to the subscribers queue and to the current state of a specific store...
|
|
46
|
-
* THIS IS NOT A REACT-HOOK, so you could use it everywhere example other hooks, and services.
|
|
47
|
-
* @return [currentState, GlobalState.IHookResult<IState, IActions, IApi>]
|
|
48
|
-
*/
|
|
49
|
-
getHookDecoupled: <IApi extends IActions extends IActionCollectionResult<IState, IActions> ? IActionCollectionResult<IState, IActions> : null>() => [
|
|
50
|
-
() => IState,
|
|
51
|
-
IHookResult<IState, IActions, IApi>
|
|
52
|
-
];
|
|
53
|
-
}
|
|
54
|
-
//# sourceMappingURL=GlobalStoreTypes.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"GlobalStoreTypes.d.ts","sourceRoot":"","sources":["../src/GlobalStoreTypes.ts"],"names":[],"mappings":"AAAA;;;EAGE;AACF,MAAM,MAAM,WAAW,CAAC,MAAM,IAAI,CAChC,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC,KAC3D,OAAO,CAAC,IAAI,CAAC,CAAC;AAEnB;;EAEE;AAEF,MAAM,MAAM,OAAO,CAAC,MAAM,IAAI,CAAC,OAAO,EAAE,GAAG,MAAM,EAAE,GAAG,EAAE,KAAK,CAAC,MAAM,EAAE,WAAW,CAAC,MAAM,CAAC,EAAE,YAAY,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC;AAE/I;;EAEE;AACF,MAAM,WAAW,uBAAuB,CAAC,MAAM;IAC7C,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;CAChC;AAED;;EAEE;AACF,MAAM,MAAM,uBAAuB,CAAC,MAAM,EAAE,QAAQ,SAAS,uBAAuB,CAAC,MAAM,CAAC,GAAG,IAAI,IAAI;KAEpG,GAAG,IAAI,MAAM,QAAQ,GAAG,CAAC,GAAG,MAAM,EAAE,GAAG,EAAE,KAAK,OAAO;CACvD,CAAC;AAEF;;EAEE;AACF,MAAM,MAAM,WAAW,CACrB,MAAM,EACN,QAAQ,SAAS,uBAAuB,CAAC,MAAM,CAAC,GAAG,IAAI,GAAG,IAAI,EAC9D,IAAI,SAAS,uBAAuB,CAAC,MAAM,EAAE,QAAQ,CAAC,GAAG,IAAI,GAAG,QAAQ,SAAS,IAAI,GAAG,IAAI,GAAG,uBAAuB,CAAC,MAAM,EAAE,QAAQ,CAAC,IACtI,IAAI,SAAS,IAAI,GACjB,WAAW,CAAC,MAAM,CAAC,GACnB,QAAQ,SAAS,uBAAuB,CAAC,MAAM,CAAC,GAChD,IAAI,SAAS,uBAAuB,CAAC,MAAM,EAAE,QAAQ,CAAC,GACpD,IAAI,GACJ,WAAW,CAAC,MAAM,CAAC,GACrB,WAAW,CAAC,MAAM,CAAC,CAAC;AAExB;;;;;;;;IAQI;AACJ,MAAM,WAAW,YAAY,CAC3B,MAAM,EAAE,QAAQ,SAAS,uBAAuB,CAAC,MAAM,CAAC,GAAG,IAAI,GAAG,IAAI;IAEtE;;;MAGE;IACF,OAAO,EAAE,CAAC,IAAI,SAAS,QAAQ,SAAS,uBAAuB,CAAC,MAAM,EAAE,QAAQ,CAAC,GAAG,uBAAuB,CAAC,MAAM,EAAE,QAAQ,CAAC,GAAG,IAAI,OAAO,MAAM;QAC/I,MAAM;QACN,WAAW,CAAC,MAAM,EAAE,QAAQ,EAAE,IAAI,CAAC;KACpC,CAAC;IAEF;;;;MAIE;IACF,gBAAgB,EAAE,CAAC,IAAI,SAAS,QAAQ,SAAS,uBAAuB,CAAC,MAAM,EAAE,QAAQ,CAAC,GAAG,uBAAuB,CAAC,MAAM,EAAE,QAAQ,CAAC,GAAG,IAAI,OAAQ;QACnJ,MAAM,MAAM;QACZ,WAAW,CAAC,MAAM,EAAE,QAAQ,EAAE,IAAI,CAAC;KACpC,CAAC;CACH"}
|