react-native-global-state-hooks 3.0.5 → 3.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +51 -170
- package/lib/GlobalStore.d.ts +50 -22
- package/lib/GlobalStore.types.d.ts +15 -2
- package/lib/GlobalStoreAbstract.d.ts +15 -0
- package/lib/bundle.js +1 -1
- package/lib/index.d.ts +1 -0
- package/package.json +2 -2
- package/README.advance.md +0 -123
package/README.md
CHANGED
|
@@ -17,22 +17,26 @@ For seen a running example of the hooks, you can check the following link: [reac
|
|
|
17
17
|
We are gonna create a global count example **useCountGlobal.ts**:
|
|
18
18
|
|
|
19
19
|
```ts
|
|
20
|
-
import {
|
|
20
|
+
import { createGlobalHook } from 'react-native-global-state-hooks';
|
|
21
21
|
|
|
22
22
|
// initialize your store with the default value of the same.
|
|
23
|
-
const
|
|
24
|
-
|
|
25
|
-
// get the hook
|
|
26
|
-
export const useCountGlobal = countStore.getHook();
|
|
23
|
+
export const useCountGlobal = createGlobalHook(0);
|
|
27
24
|
|
|
28
25
|
// inside your component just call...
|
|
29
|
-
const [count, setCount] = useCountGlobal(); // no
|
|
26
|
+
const [count, setCount] = useCountGlobal(); // no parameters are needed since this is a global store
|
|
30
27
|
|
|
31
28
|
// That's it, that's a global store... Strongly typed, with a global-hook that we could reuse cross all our react-components.
|
|
32
29
|
|
|
33
30
|
// #### Optionally you are able to use a decoupled hook,
|
|
34
31
|
// #### This function is linked to the store hooks but is not a hook himself.
|
|
35
32
|
|
|
33
|
+
// we could create the store in this way to get extra capabilities
|
|
34
|
+
const countStore = new GlobalStore(0);
|
|
35
|
+
|
|
36
|
+
// the useCountGlobal works exactly the same
|
|
37
|
+
export const useCountGlobal = countStore.getHook();
|
|
38
|
+
|
|
39
|
+
// but now we are also able to get a decoupled hook
|
|
36
40
|
export const [getCount, sendCount] = countStore.getHookDecoupled();
|
|
37
41
|
|
|
38
42
|
// @example
|
|
@@ -109,14 +113,14 @@ Let's see a trivial example:
|
|
|
109
113
|
```JSX
|
|
110
114
|
import { useCountGlobal, sendCount } from './useCountGlobal'
|
|
111
115
|
|
|
112
|
-
const
|
|
116
|
+
const CountDisplayComponent: React.FC = () => {
|
|
113
117
|
const [count] = useCountGlobal();
|
|
114
118
|
|
|
115
119
|
return (<Text>{count}<Text/>);
|
|
116
120
|
}
|
|
117
121
|
|
|
118
122
|
// here we have a separate component that is gonna handle the state of the previous component we created,
|
|
119
|
-
// this new component is not gonna be affected by the changes applied on <
|
|
123
|
+
// this new component is not gonna be affected by the changes applied on <CountDisplayComponent/>
|
|
120
124
|
// Stage2 does not need to be updated once the global count changes
|
|
121
125
|
const CountManagerComponent: React.FC = () => {
|
|
122
126
|
const increaseClick = useCallback(() => sendCount(count => count + 1), []);
|
|
@@ -137,13 +141,13 @@ const CountManagerComponent: React.FC = () => {
|
|
|
137
141
|
|
|
138
142
|
Implementing extra functionality to extend the capabilities of the GlobalStorage couldn't be easier!!!
|
|
139
143
|
|
|
140
|
-
Here is an example of how you could create your custom store that for example stores the state into a async-storage
|
|
144
|
+
Here is an example of how you could create your custom store that for example stores the state into a async-storage persistent...
|
|
141
145
|
|
|
142
146
|
You could just use this code right as it is by just adding also into your project **@react-native-async-storage** or whatever another async storage library.
|
|
143
147
|
|
|
144
148
|
```ts
|
|
145
149
|
import asyncStorage from '@react-native-async-storage/async-storage';
|
|
146
|
-
import {
|
|
150
|
+
import { formatFromStore, formatToStore } from 'json-storage-formatter';
|
|
147
151
|
|
|
148
152
|
import {
|
|
149
153
|
GlobalStore as GlobalStoreBase,
|
|
@@ -153,120 +157,67 @@ import {
|
|
|
153
157
|
StateSetter,
|
|
154
158
|
} from 'react-native-global-state-hooks';
|
|
155
159
|
|
|
156
|
-
/**
|
|
157
|
-
* GlobalStore is an store that could also persist the state in the async storage
|
|
158
|
-
* @template {TState} TState - The state of the store
|
|
159
|
-
* @template {TMetadata} TMetadata - The metadata of the store, it must contain a readonly property called isAsyncStorageReady which cannot be set from outside the store
|
|
160
|
-
* @template {TStateSetter} TStateSetter - The storeActionsConfig of the store
|
|
161
|
-
*/
|
|
162
160
|
export class GlobalStore<
|
|
163
161
|
TState,
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
> extends
|
|
172
|
-
/**
|
|
173
|
-
* Config for the async storage
|
|
174
|
-
* includes the asyncStorageKey and the metadata which will be used to determine if the async storage is ready or not
|
|
175
|
-
* @template {TState} TState - The state of the store
|
|
176
|
-
* @template {TMetadata} TMetadata - The metadata of the store
|
|
177
|
-
* @template {TStateSetter} TStateSetter - The storeActionsConfig of the store
|
|
178
|
-
**/
|
|
179
|
-
protected config: StorageConfig<TState, TMetadata, TStateSetter> = {};
|
|
180
|
-
|
|
181
|
-
/**
|
|
182
|
-
* Creates a new instance of the GlobalStore
|
|
183
|
-
* @param {TState} state - The initial state of the store
|
|
184
|
-
* @param {GlobalStoreConfig<TState, TMetadata, ActionCollectionConfig<TState, TMetadata> | StateSetter<TState>> & { asyncStorageKey: string; }} config - The config of the store
|
|
185
|
-
* @param {GlobalStoreConfig<TState, TMetadata, ActionCollectionConfig<TState, TMetadata> | StateSetter<TState>> & { asyncStorageKey: string; }} config.metadata - The metadata of the store which will be used to determine if the async storage is ready or not, also it could store no reactive data
|
|
186
|
-
* @param {GlobalStoreConfig<TState, TMetadata, ActionCollectionConfig<TState, TMetadata> | StateSetter<TState>> & { asyncStorageKey: string; }} config.asyncStorageKey - The key of the async storage
|
|
187
|
-
* @param {GlobalStoreConfig<TState, TMetadata, ActionCollectionConfig<TState, TMetadata> | StateSetter<TState>> & { asyncStorageKey: string; }} config.onInit - The callback that will be called once the store is created
|
|
188
|
-
* @param {GlobalStoreConfig<TState, TMetadata, ActionCollectionConfig<TState, TMetadata> | StateSetter<TState>> & { asyncStorageKey: string; }} config.onStateChange - The callback that will be called once the state is changed
|
|
189
|
-
* @param {GlobalStoreConfig<TState, TMetadata, ActionCollectionConfig<TState, TMetadata> | StateSetter<TState>> & { asyncStorageKey: string; }} config.onSubscribed - The callback that will be called every time a new component is subscribed to the store
|
|
190
|
-
* @param {GlobalStoreConfig<TState, TMetadata, ActionCollectionConfig<TState, TMetadata> | StateSetter<TState>> & { asyncStorageKey: string; }} config.computePreventStateChange - The callback that will be called before the state is changed, if it returns true the state will not be changed
|
|
191
|
-
* @param {TStateSetter} setterConfig - The actions configuration object (optional) (default: null) if not null the store manipulation will be done through the actions
|
|
192
|
-
*/
|
|
162
|
+
TMetadata extends {
|
|
163
|
+
asyncStorageKey?: string;
|
|
164
|
+
isAsyncStorageReady?: boolean;
|
|
165
|
+
},
|
|
166
|
+
TStateSetter extends
|
|
167
|
+
| ActionCollectionConfig<TState, TMetadata>
|
|
168
|
+
| StateSetter<TState> = StateSetter<TState>
|
|
169
|
+
> extends GlobalStoreAbstract<TState, TMetadata, TStateSetter> {
|
|
193
170
|
constructor(
|
|
194
171
|
state: TState,
|
|
195
|
-
config:
|
|
172
|
+
config: GlobalStoreConfig<TState, TMetadata, TStateSetter> = {},
|
|
196
173
|
setterConfig: TStateSetter | null = null
|
|
197
174
|
) {
|
|
198
|
-
|
|
199
|
-
config ?? ({} as StorageConfig<TState, TMetadata, TStateSetter>);
|
|
200
|
-
|
|
201
|
-
super(state, configParameters, setterConfig as TStateSetter);
|
|
202
|
-
|
|
203
|
-
// if there is not async storage key this is not a persistent store
|
|
204
|
-
const isAsyncStorageReady: boolean | null = asyncStorageKey ? false : null;
|
|
205
|
-
|
|
206
|
-
this.config = {
|
|
207
|
-
...config,
|
|
208
|
-
metadata: {
|
|
209
|
-
...((configParameters.metadata ?? {}) as TMetadata),
|
|
210
|
-
isAsyncStorageReady,
|
|
211
|
-
},
|
|
212
|
-
};
|
|
213
|
-
|
|
214
|
-
const hasInitCallbacks = !!(asyncStorageKey || onInit);
|
|
215
|
-
if (!hasInitCallbacks) return;
|
|
175
|
+
super(state, config, setterConfig);
|
|
216
176
|
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
this.onInit(parameters);
|
|
220
|
-
onInit?.(parameters);
|
|
177
|
+
this.initialize();
|
|
221
178
|
}
|
|
222
179
|
|
|
223
|
-
|
|
224
|
-
* This method will be called once the store is created after the constructor,
|
|
225
|
-
* this method is different from the onInit of the config property and it won't be overridden
|
|
226
|
-
*/
|
|
227
|
-
protected onInit = async ({
|
|
180
|
+
protected onInitialize = async ({
|
|
228
181
|
setState,
|
|
229
182
|
setMetadata,
|
|
230
183
|
getMetadata,
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
const { asyncStorageKey } = this.config;
|
|
184
|
+
getState,
|
|
185
|
+
}: StateConfigCallbackParam<TState, TMetadata, TStateSetter>) => {
|
|
186
|
+
const metadata = getMetadata();
|
|
187
|
+
const { asyncStorageKey } = metadata;
|
|
188
|
+
|
|
237
189
|
if (!asyncStorageKey) return;
|
|
238
190
|
|
|
239
191
|
const storedItem = (await asyncStorage.getItem(asyncStorageKey)) as string;
|
|
240
|
-
|
|
241
192
|
setMetadata({
|
|
242
|
-
...
|
|
193
|
+
...metadata,
|
|
243
194
|
isAsyncStorageReady: true,
|
|
244
195
|
});
|
|
245
196
|
|
|
246
197
|
if (storedItem === null) {
|
|
247
|
-
const state =
|
|
198
|
+
const state = getState();
|
|
248
199
|
|
|
249
|
-
//
|
|
250
|
-
return setState(state);
|
|
200
|
+
// force the re-render of the subscribed components even if the state is the same
|
|
201
|
+
return setState(state, { forceUpdate: true });
|
|
251
202
|
}
|
|
252
203
|
|
|
253
|
-
const
|
|
254
|
-
|
|
204
|
+
const items = formatFromStore<TState>(storedItem, {
|
|
205
|
+
jsonParse: true,
|
|
206
|
+
});
|
|
255
207
|
|
|
256
|
-
setState(items);
|
|
208
|
+
setState(items, { forceUpdate: true });
|
|
257
209
|
};
|
|
258
210
|
|
|
259
|
-
protected
|
|
211
|
+
protected onChange = ({
|
|
212
|
+
getMetadata,
|
|
260
213
|
getState,
|
|
261
|
-
}: StateChangesParam<
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
NonNullable<TStateSetter>
|
|
265
|
-
>) => {
|
|
266
|
-
const { asyncStorageKey } = this.config;
|
|
214
|
+
}: StateChangesParam<TState, TMetadata, NonNullable<TStateSetter>>) => {
|
|
215
|
+
const { asyncStorageKey } = getMetadata();
|
|
216
|
+
|
|
267
217
|
if (!asyncStorageKey) return;
|
|
268
218
|
|
|
269
219
|
const state = getState();
|
|
220
|
+
|
|
270
221
|
const formattedObject = formatToStore(state, {
|
|
271
222
|
stringify: true,
|
|
272
223
|
});
|
|
@@ -274,76 +225,6 @@ export class GlobalStore<
|
|
|
274
225
|
asyncStorage.setItem(asyncStorageKey, formattedObject);
|
|
275
226
|
};
|
|
276
227
|
}
|
|
277
|
-
|
|
278
|
-
/**
|
|
279
|
-
* Metadata of the store
|
|
280
|
-
* @template {TMetadata} TMetadata - The metadata type which also contains the isAsyncStorageReady property
|
|
281
|
-
*/
|
|
282
|
-
type StorageMetadata<TMetadata> = Omit<TMetadata, 'isAsyncStorageReady'> & {
|
|
283
|
-
readonly isAsyncStorageReady?: boolean | null;
|
|
284
|
-
};
|
|
285
|
-
|
|
286
|
-
/**
|
|
287
|
-
* The setter of the store
|
|
288
|
-
* @template {TState} TState - The state of the store
|
|
289
|
-
* @template {TMetadata} TMetadata - The metadata of the store, it must contain a readonly property called isAsyncStorageReady which cannot be set from outside the store
|
|
290
|
-
* */
|
|
291
|
-
type StorageSetter<TState, TMetadata> =
|
|
292
|
-
| ActionCollectionConfig<TState, StorageMetadata<TMetadata>>
|
|
293
|
-
| StateSetter<TState>
|
|
294
|
-
| null;
|
|
295
|
-
|
|
296
|
-
/**
|
|
297
|
-
* Config for the async storage
|
|
298
|
-
* includes the asyncStorageKey
|
|
299
|
-
* @template {TState} TState - The state of the store
|
|
300
|
-
* @template {TMetadata} TMetadata - The metadata of the store, it must contain a readonly property called isAsyncStorageReady which cannot be set from outside the store
|
|
301
|
-
* @template {TStateSetter} TStateSetter - The storeActionsConfig of the store
|
|
302
|
-
*/
|
|
303
|
-
type StorageConfig<
|
|
304
|
-
TState,
|
|
305
|
-
TMetadata extends { readonly isAsyncStorageReady?: never },
|
|
306
|
-
TStateSetter extends
|
|
307
|
-
| ActionCollectionConfig<TState, StorageMetadata<TMetadata>>
|
|
308
|
-
| StateSetter<TState>
|
|
309
|
-
| null = StateSetter<TState>
|
|
310
|
-
> = {
|
|
311
|
-
asyncStorageKey?: string;
|
|
312
|
-
|
|
313
|
-
metadata?: TMetadata;
|
|
314
|
-
|
|
315
|
-
onInit?: (
|
|
316
|
-
parameters: StateConfigCallbackParam<
|
|
317
|
-
TState,
|
|
318
|
-
StorageMetadata<TMetadata>,
|
|
319
|
-
NonNullable<TStateSetter>
|
|
320
|
-
>
|
|
321
|
-
) => void;
|
|
322
|
-
|
|
323
|
-
onStateChanged?: (
|
|
324
|
-
parameters: StateChangesParam<
|
|
325
|
-
TState,
|
|
326
|
-
StorageMetadata<TMetadata>,
|
|
327
|
-
NonNullable<TStateSetter>
|
|
328
|
-
>
|
|
329
|
-
) => void;
|
|
330
|
-
|
|
331
|
-
onSubscribed?: (
|
|
332
|
-
parameters: StateConfigCallbackParam<
|
|
333
|
-
TState,
|
|
334
|
-
StorageMetadata<TMetadata>,
|
|
335
|
-
NonNullable<TStateSetter>
|
|
336
|
-
>
|
|
337
|
-
) => void;
|
|
338
|
-
|
|
339
|
-
computePreventStateChange?: (
|
|
340
|
-
parameters: StateChangesParam<
|
|
341
|
-
TState,
|
|
342
|
-
StorageMetadata<TMetadata>,
|
|
343
|
-
NonNullable<TStateSetter>
|
|
344
|
-
>
|
|
345
|
-
) => boolean;
|
|
346
|
-
};
|
|
347
228
|
```
|
|
348
229
|
|
|
349
230
|
The methods **formatToStore** and **formatFromStore** are part of another library of my [json-storage-formatter](https://www.npmjs.com/package/json-storage-formatter)...
|
|
@@ -362,7 +243,7 @@ const [count, setCount, { isAsyncStorageReady }] = useCountGlobal();
|
|
|
362
243
|
|
|
363
244
|
Originally the library was implementing persistent storage by using the package **@react-native-async-storage**, but not all people want to use it or need to use it... so it has been removed. Feel free to use the above example to get back that functionality if you were using the previous versions of the package.
|
|
364
245
|
|
|
365
|
-
You could find this example on the [**GitHub** of the project](https://github.com/johnny-quesada-developer/json-storage-formatter), between the unit test sources when the case scenario was tested [
|
|
246
|
+
You could find this example on the [**GitHub** of the project](https://github.com/johnny-quesada-developer/json-storage-formatter), between the unit test sources when the case scenario was tested [GlobalStoreAsync.ts](https://github.com/johnny-quesada-developer/react-native-global-state-hooks/blob/master/%40tests/__test__/GlobalStoreAsyc.ts)
|
|
366
247
|
|
|
367
248
|
...
|
|
368
249
|
|
|
@@ -380,7 +261,7 @@ const initialValue = 0;
|
|
|
380
261
|
|
|
381
262
|
const config = {
|
|
382
263
|
// this is not reactive information that you could also store in the async storage
|
|
383
|
-
//
|
|
264
|
+
// updating the metadata will not trigger the onStateChanged method or any update on the components
|
|
384
265
|
metadata: null,
|
|
385
266
|
|
|
386
267
|
// The lifecycle callbacks are: onInit, onStateChanged, onSubscribed and computePreventStateChange
|
|
@@ -756,7 +637,7 @@ const App = () => {
|
|
|
756
637
|
return (
|
|
757
638
|
<UserProvider>
|
|
758
639
|
<CountProvider>
|
|
759
|
-
{/* lets create two
|
|
640
|
+
{/* lets create two components instead of one */}
|
|
760
641
|
<ComponentSetter />
|
|
761
642
|
<Component />
|
|
762
643
|
</CountProvider>
|
|
@@ -895,14 +776,14 @@ There is also a third element in the tuple which is a function for getting the m
|
|
|
895
776
|
```tsx
|
|
896
777
|
const [, , getMetadata] = new GlobalStore(0, {
|
|
897
778
|
metadata: {
|
|
898
|
-
|
|
779
|
+
isStoredSynchronized: false,
|
|
899
780
|
},
|
|
900
781
|
}).getHookDecoupled();
|
|
901
782
|
|
|
902
|
-
console.log(getMetadata().
|
|
783
|
+
console.log(getMetadata().isStoredSynchronized); // false
|
|
903
784
|
```
|
|
904
785
|
|
|
905
|
-
The setMetadata is part of the store tools, so it can be used in the actions, but
|
|
786
|
+
The setMetadata is part of the store tools, so it can be used in the actions, but again the metadata is not reactive!! so it will not trigger a re-render on the subscribers
|
|
906
787
|
|
|
907
788
|
...
|
|
908
789
|
|
package/lib/GlobalStore.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Dispatch, SetStateAction } from 'react';
|
|
2
|
-
import { ActionCollectionConfig, StateSetter, GlobalStoreConfig, ActionCollectionResult, StateConfigCallbackParam } from './GlobalStore.types';
|
|
2
|
+
import { ActionCollectionConfig, StateSetter, GlobalStoreConfig, ActionCollectionResult, StateConfigCallbackParam, StateChangesParam } from './GlobalStore.types';
|
|
3
3
|
/**
|
|
4
4
|
* The GlobalStore class is the main class of the library and it is used to create a GlobalStore instances
|
|
5
5
|
* @template {TState} TState - The type of the state object
|
|
@@ -7,13 +7,14 @@ import { ActionCollectionConfig, StateSetter, GlobalStoreConfig, ActionCollectio
|
|
|
7
7
|
* @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
|
|
8
8
|
* */
|
|
9
9
|
export declare class GlobalStore<TState, TMetadata = null, TStateSetter extends ActionCollectionConfig<TState, TMetadata> | StateSetter<TState> | null = StateSetter<TState>> {
|
|
10
|
-
protected state: TState;
|
|
11
10
|
protected setterConfig: TStateSetter | null;
|
|
12
11
|
/**
|
|
13
12
|
* list of all the subscribers setState functions
|
|
14
13
|
* @template {TState} TState - The type of the state object
|
|
15
14
|
* */
|
|
16
|
-
subscribers: Set<StateSetter<
|
|
15
|
+
subscribers: Set<StateSetter<{
|
|
16
|
+
state: TState;
|
|
17
|
+
}>>;
|
|
17
18
|
/**
|
|
18
19
|
* additional configuration for the store
|
|
19
20
|
* @template {TState} TState - The type of the state object
|
|
@@ -75,6 +76,16 @@ export declare class GlobalStore<TState, TMetadata = null, TStateSetter extends
|
|
|
75
76
|
* @returns {boolean} - true to prevent the state change, false to allow the state change
|
|
76
77
|
* */
|
|
77
78
|
protected computePreventStateChange?: GlobalStoreConfig<TState, TMetadata, TStateSetter>['computePreventStateChange'];
|
|
79
|
+
/**
|
|
80
|
+
* We use a wrapper in order to be able to force the state update when necessary even with primitive types
|
|
81
|
+
*/
|
|
82
|
+
protected stateWrapper: {
|
|
83
|
+
state: TState;
|
|
84
|
+
};
|
|
85
|
+
/**
|
|
86
|
+
* @deprecated direct modifications of the state could end up in unexpected behaviors
|
|
87
|
+
*/
|
|
88
|
+
protected get state(): TState;
|
|
78
89
|
/**
|
|
79
90
|
* Create a simple global store
|
|
80
91
|
* @param {TState} state - The initial state
|
|
@@ -104,17 +115,7 @@ export declare class GlobalStore<TState, TMetadata = null, TStateSetter extends
|
|
|
104
115
|
* @param {TStateSetter} setterConfig - The actions configuration object (optional) (default: null) if not null the store manipulation will be done through the actions
|
|
105
116
|
* */
|
|
106
117
|
constructor(state: TState, config: GlobalStoreConfig<TState, TMetadata, TStateSetter>, setterConfig: TStateSetter);
|
|
107
|
-
protected
|
|
108
|
-
/**
|
|
109
|
-
* gets a clone of the state
|
|
110
|
-
* @returns {TState} - The state clone
|
|
111
|
-
* */
|
|
112
|
-
protected getStateClone: () => TState;
|
|
113
|
-
/**
|
|
114
|
-
* gets a clone of the metadata
|
|
115
|
-
* @returns {TMetadata} - The metadata clone
|
|
116
|
-
* */
|
|
117
|
-
protected getMetadataClone: () => TMetadata;
|
|
118
|
+
protected initialize: () => void;
|
|
118
119
|
/**
|
|
119
120
|
* set the state and update all the subscribers
|
|
120
121
|
* @param {StateSetter<TState>} setter - The setter function or the value to set
|
|
@@ -122,7 +123,9 @@ export declare class GlobalStore<TState, TMetadata = null, TStateSetter extends
|
|
|
122
123
|
* */
|
|
123
124
|
protected setState: ({ invokerSetState, state, }: {
|
|
124
125
|
state: TState;
|
|
125
|
-
invokerSetState?:
|
|
126
|
+
invokerSetState?: Dispatch<SetStateAction<{
|
|
127
|
+
state: TState;
|
|
128
|
+
}>>;
|
|
126
129
|
}) => void;
|
|
127
130
|
/**
|
|
128
131
|
* Set the value of the metadata property, this is no reactive and will not trigger a re-render
|
|
@@ -137,7 +140,9 @@ export declare class GlobalStore<TState, TMetadata = null, TStateSetter extends
|
|
|
137
140
|
* @returns {StateConfigCallbackParam<TState, TMetadata>} - The parameters object
|
|
138
141
|
* */
|
|
139
142
|
protected getConfigCallbackParam: ({ invokerSetState, }: {
|
|
140
|
-
invokerSetState?: React.Dispatch<React.SetStateAction<
|
|
143
|
+
invokerSetState?: React.Dispatch<React.SetStateAction<{
|
|
144
|
+
state: TState;
|
|
145
|
+
}>>;
|
|
141
146
|
}) => StateConfigCallbackParam<TState, TMetadata, TStateSetter>;
|
|
142
147
|
/**
|
|
143
148
|
* Returns a custom hook that allows to handle a global state
|
|
@@ -155,14 +160,18 @@ export declare class GlobalStore<TState, TMetadata = null, TStateSetter extends
|
|
|
155
160
|
* @returns {StateSetter<TState>} - The state setter
|
|
156
161
|
* */
|
|
157
162
|
protected getSetStateWrapper: ({ invokerSetState, }?: {
|
|
158
|
-
invokerSetState?: React.Dispatch<React.SetStateAction<
|
|
163
|
+
invokerSetState?: React.Dispatch<React.SetStateAction<{
|
|
164
|
+
state: TState;
|
|
165
|
+
}>>;
|
|
159
166
|
}) => StateSetter<TState>;
|
|
160
167
|
/**
|
|
161
168
|
* Returns the state setter or the actions map
|
|
162
169
|
* @param {{ invokerSetState?: React.Dispatch<React.SetStateAction<TState>> }} parameters - 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
|
|
163
170
|
* @returns {TStateSetter} - The state setter or the actions map
|
|
164
171
|
* */
|
|
165
|
-
protected getStateOrchestrator(invokerSetState?: React.Dispatch<React.SetStateAction<
|
|
172
|
+
protected getStateOrchestrator(invokerSetState?: React.Dispatch<React.SetStateAction<{
|
|
173
|
+
state: TState;
|
|
174
|
+
}>>): StateSetter<TState> | ActionCollectionResult<TState, TMetadata, TStateSetter>;
|
|
166
175
|
/**
|
|
167
176
|
* Calculate whenever or not we should compute the callback parameters on the state change
|
|
168
177
|
* @returns {boolean} - True if we should compute the callback parameters on the state change
|
|
@@ -175,16 +184,35 @@ export declare class GlobalStore<TState, TMetadata = null, TStateSetter extends
|
|
|
175
184
|
* - computePreventStateChange (if defined) - this function is executed before the state change and it should return a boolean value that will be used to determine if the state change should be prevented or not
|
|
176
185
|
* @param {{ setter: StateSetter<TState>; invokerSetState?: React.Dispatch<React.SetStateAction<TState>> }} parameters - The state setter and 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
|
|
177
186
|
*/
|
|
178
|
-
protected computeSetState: ({ setter, invokerSetState, }: {
|
|
187
|
+
protected computeSetState: ({ setter, invokerSetState, forceUpdate, }: {
|
|
179
188
|
setter: StateSetter<TState>;
|
|
180
|
-
invokerSetState?: React.Dispatch<React.SetStateAction<
|
|
189
|
+
invokerSetState?: React.Dispatch<React.SetStateAction<{
|
|
190
|
+
state: TState;
|
|
191
|
+
}>>;
|
|
192
|
+
forceUpdate: boolean;
|
|
181
193
|
}) => void;
|
|
182
194
|
/**
|
|
183
195
|
* This creates a map of actions that can be used to modify or interact with the state
|
|
184
196
|
* @param {{ invokerSetState?: React.Dispatch<React.SetStateAction<TState>> }} parameters - 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
|
|
185
197
|
* @returns {ActionCollectionResult<TState, TMetadata, TStateSetter>} - The actions map result of the configuration object passed to the constructor
|
|
186
198
|
* */
|
|
187
|
-
protected getStoreActionsMap: ({ invokerSetState, }
|
|
188
|
-
invokerSetState?: React.Dispatch<React.SetStateAction<
|
|
199
|
+
protected getStoreActionsMap: ({ invokerSetState, }?: {
|
|
200
|
+
invokerSetState?: React.Dispatch<React.SetStateAction<{
|
|
201
|
+
state: TState;
|
|
202
|
+
}>>;
|
|
189
203
|
}) => ActionCollectionResult<TState, TMetadata, TStateSetter>;
|
|
190
204
|
}
|
|
205
|
+
/**
|
|
206
|
+
* Creates a global hook that can be used to access the state and actions across the application
|
|
207
|
+
* @param {TState} state - The initial state of the store
|
|
208
|
+
* @param {GlobalStoreConfig<TState, TMetadata, TStateSetter>} config - The configuration object of the store
|
|
209
|
+
* @param {TStateSetter | null} setterConfig - The configuration object of the state setter (optional) (default: null)
|
|
210
|
+
* @returns {GlobalStoreHook<TState, TMetadata, TStateSetter>} - The hook that can be used to access the state and actions across the application
|
|
211
|
+
*/
|
|
212
|
+
export declare const createGlobalHook: <TState, TMetadata = null, TStateSetter extends ActionCollectionConfig<TState, TMetadata> | StateSetter<TState> = StateSetter<TState>>(state: TState, config?: {
|
|
213
|
+
metadata?: TMetadata;
|
|
214
|
+
onInit?: (parameters: StateConfigCallbackParam<TState, TMetadata, TStateSetter>) => void;
|
|
215
|
+
onStateChanged?: (parameters: StateChangesParam<TState, TMetadata, TStateSetter>) => void;
|
|
216
|
+
onSubscribed?: (parameters: StateConfigCallbackParam<TState, TMetadata, TStateSetter>) => void;
|
|
217
|
+
computePreventStateChange?: (parameters: StateChangesParam<TState, TMetadata, TStateSetter>) => boolean;
|
|
218
|
+
}, setterConfig?: TStateSetter) => () => [TState, TStateSetter extends StateSetter<TState> ? StateSetter<TState> : ActionCollectionResult<TState, TMetadata, TStateSetter>, TMetadata];
|
|
@@ -2,7 +2,18 @@
|
|
|
2
2
|
* @param {StateSetter<TState>} setter - add a new state to an existing state
|
|
3
3
|
* @returns {void} result - void
|
|
4
4
|
*/
|
|
5
|
-
export type StateSetter<TState> = (setter: TState | ((state: TState) => TState)
|
|
5
|
+
export type StateSetter<TState> = (setter: TState | ((state: TState) => TState),
|
|
6
|
+
/**
|
|
7
|
+
* This parameter indicate whether we should force the re-render of the subscribers even if the state is the same,
|
|
8
|
+
* Do
|
|
9
|
+
*/
|
|
10
|
+
{ forceUpdate, }?: {
|
|
11
|
+
/**
|
|
12
|
+
* @deprecated forceUpdate normally should not be used inside components
|
|
13
|
+
* Use this flag just in custom implementations of the global store
|
|
14
|
+
*/
|
|
15
|
+
forceUpdate?: boolean;
|
|
16
|
+
}) => void;
|
|
6
17
|
/**
|
|
7
18
|
* Parameters of the onStateChanged callback function
|
|
8
19
|
* @param {TState} state - the new state
|
|
@@ -13,19 +24,21 @@ export type StateChanges<TState> = {
|
|
|
13
24
|
previousState?: TState;
|
|
14
25
|
};
|
|
15
26
|
/**
|
|
16
|
-
* Callbacks to be passed to the
|
|
27
|
+
* Callbacks to be passed to the configurations function of the store
|
|
17
28
|
* @template {TState} TState - The state type
|
|
18
29
|
* @template {TMetadata} TMetadata - The metadata type
|
|
19
30
|
* @property {StateSetter<TState>} setMetadata - Set the metadata
|
|
20
31
|
* @property {StateSetter<TState>} setState - Set the state
|
|
21
32
|
* @property {() => TState} getState - Get the state
|
|
22
33
|
* @property {() => TMetadata} getMetadata - Get the metadata
|
|
34
|
+
* @property {ActionCollectionResult<TState, TMetadata>} actions - The actions collection if any
|
|
23
35
|
**/
|
|
24
36
|
export type StoreTools<TState, TMetadata = null> = {
|
|
25
37
|
setMetadata: StateSetter<TMetadata>;
|
|
26
38
|
setState: StateSetter<TState>;
|
|
27
39
|
getState: () => TState;
|
|
28
40
|
getMetadata: () => TMetadata;
|
|
41
|
+
actions: ActionCollectionResult<TState, TMetadata>;
|
|
29
42
|
};
|
|
30
43
|
/**
|
|
31
44
|
* Basic contract for the storeActionsConfig configuration
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { StateSetter, StateConfigCallbackParam, StateChangesParam, ActionCollectionConfig, GlobalStoreConfig } from 'GlobalStore.types';
|
|
2
|
+
import { GlobalStore } from './GlobalStore';
|
|
3
|
+
/**
|
|
4
|
+
* @description
|
|
5
|
+
* Use this class to extends the capabilities of the GlobalStore.
|
|
6
|
+
* by implementing the abstract methods onInitialize and onChange.
|
|
7
|
+
* You can use this class to create a store with async storage.
|
|
8
|
+
*/
|
|
9
|
+
export declare abstract class GlobalStoreAbstract<TState, TMetadata = null, TStateSetter extends ActionCollectionConfig<TState, TMetadata> | StateSetter<TState> | null = StateSetter<TState>> extends GlobalStore<TState, TMetadata, TStateSetter> {
|
|
10
|
+
constructor(state: TState, config?: GlobalStoreConfig<TState, TMetadata, TStateSetter>, setterConfig?: TStateSetter | null);
|
|
11
|
+
protected onInit: (parameters: StateConfigCallbackParam<TState, TMetadata, TStateSetter>) => void;
|
|
12
|
+
protected onStateChanged: (parameters: StateChangesParam<TState, TMetadata, NonNullable<TStateSetter>>) => void;
|
|
13
|
+
protected abstract onInitialize: ({ setState, setMetadata, getMetadata, getState, actions, }: StateConfigCallbackParam<TState, TMetadata, TStateSetter>) => void;
|
|
14
|
+
protected abstract onChange: ({ setState, setMetadata, getMetadata, getState, actions, }: StateChangesParam<TState, TMetadata, NonNullable<TStateSetter>>) => void;
|
|
15
|
+
}
|
package/lib/bundle.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e(require("react")):"function"==typeof define&&define.amd?define(["react"],e):"object"==typeof exports?exports["react-native-global-state-hooks"]=e(require("react")):t["react-native-global-state-hooks"]=e(t.react)}(this,(t=>{return e={774:(t,e,r)=>{"use strict";function n(t){return n="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},n(t)}function o(t,e){(null==e||e>t.length)&&(e=t.length);for(var r=0,n=new Array(e);r<e;r++)n[r]=t[r];return n}function a(t,e){for(var r=0;r<e.length;r++){var n=e[r];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(t,i(n.key),n)}}function i(t){var e=function(t,e){if("object"!==n(t)||null===t)return t;var r=t[Symbol.toPrimitive];if(void 0!==r){var o=r.call(t,"string");if("object"!==n(o))return o;throw new TypeError("@@toPrimitive must return a primitive value.")}return String(t)}(t);return"symbol"===n(e)?e:String(e)}Object.defineProperty(e,"__esModule",{value:!0}),e.GlobalStore=void 0;var u=r(684),c=r(156),l=function(){function t(e){var r=this,n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},a=arguments.length>2&&void 0!==arguments[2]?arguments[2]:null;!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,t),this.state=e,this.setterConfig=a,this.subscribers=new Set,this.config={metadata:null},this.onInit=null,this.onStateChanged=null,this.onSubscribed=null,this.computePreventStateChange=null,this.onInitializeStore=function(){var t=r.onInit,e=r.config.onInit;if(t||e){var n=r.getConfigCallbackParam({});null==t||t(n),null==e||e(n)}},this.getStateClone=function(){return(0,u.clone)(r.state)},this.getMetadataClone=function(){var t,e;return(0,u.clone)(null!==(e=null===(t=r.config)||void 0===t?void 0:t.metadata)&&void 0!==e?e:null)},this.setState=function(t){var e=t.invokerSetState,n=t.state;r.state=n,null==e||e(n),r.subscribers.forEach((function(t){t!==e&&t(n)}))},this.setMetadata=function(t){var e,n="function"==typeof t?t(r.getMetadataClone()):t;r.config=Object.assign(Object.assign({},null!==(e=r.config)&&void 0!==e?e:{}),{metadata:n})},this.getConfigCallbackParam=function(t){var e=t.invokerSetState;return{setMetadata:r.setMetadata,getMetadata:r.getMetadataClone,getState:r.getStateClone,setState:r.getSetStateWrapper({invokerSetState:e}),actions:r.getStoreActionsMap({})}},this.getHook=function(){return function(){var t,e,n=(t=(0,c.useState)((function(){return r.state})),e=2,function(t){if(Array.isArray(t))return t}(t)||function(t,e){var r=null==t?null:"undefined"!=typeof Symbol&&t[Symbol.iterator]||t["@@iterator"];if(null!=r){var n,o,a,i,u=[],c=!0,l=!1;try{if(a=(r=r.call(t)).next,0===e){if(Object(r)!==r)return;c=!1}else for(;!(c=(n=a.call(r)).done)&&(u.push(n.value),u.length!==e);c=!0);}catch(t){l=!0,o=t}finally{try{if(!c&&null!=r.return&&(i=r.return(),Object(i)!==i))return}finally{if(l)throw o}}return u}}(t,e)||function(t,e){if(t){if("string"==typeof t)return o(t,e);var r=Object.prototype.toString.call(t).slice(8,-1);return"Object"===r&&t.constructor&&(r=t.constructor.name),"Map"===r||"Set"===r?Array.from(t):"Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r)?o(t,e):void 0}}(t,e)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()),a=n[0],i=n[1];return(0,c.useEffect)((function(){r.subscribers.add(i);var t=r.onSubscribed,e=r.config.onSubscribed;if(t||e){var n=r.getConfigCallbackParam({invokerSetState:i});null==t||t(n),null==e||e(n)}return function(){r.subscribers.delete(i)}}),[]),[a,r.getStateOrchestrator(i),r.getMetadataClone()]}},this.getHookDecoupled=function(){var t=r.getStateClone,e=r.getMetadataClone;return[t,r.getStateOrchestrator(),e]},this.getSetStateWrapper=function(){var t=(arguments.length>0&&void 0!==arguments[0]?arguments[0]:{}).invokerSetState;return function(e){r.computeSetState({invokerSetState:t,setter:e})}},this.hasStateCallbacks=function(){var t=r.computePreventStateChange,e=r.onStateChanged,n=r.config,o=n.computePreventStateChange,a=n.onStateChanged;return!!(t||o||e||a)},this.computeSetState=function(t){var e=t.setter,n=t.invokerSetState,o="function"==typeof e,a=r.getStateClone(),i=o?e(a):e,u=r.hasStateCallbacks(),c=u&&r.getStoreActionsMap({}),l=u&&r.getSetStateWrapper({invokerSetState:n}),s={setMetadata:r.setMetadata,getMetadata:r.getMetadataClone,setState:l,getState:r.getStateClone,actions:c,previousState:a,state:i},f=r.computePreventStateChange,v=r.config.computePreventStateChange;if(!f&&!v||!(null==f?void 0:f(s))&&!(null==v?void 0:v(s))){r.setState({invokerSetState:n,state:i});var g=r.onStateChanged,S=r.config.onStateChanged;(g||S)&&(null==g||g(s),null==S||S(s))}},this.getStoreActionsMap=function(t){var e=t.invokerSetState;if(!r.setterConfig)return null;var n=r.setterConfig,o=r.setMetadata,a=n,u=Object.keys(a),c=r.getSetStateWrapper({invokerSetState:e}),l=r.getStateClone,s=r.getMetadataClone,f=u.reduce((function(t,e){return Object.assign(Object.assign({},t),(r={},u=function(){for(var t=a[e],r=arguments.length,n=new Array(r),i=0;i<r;i++)n[i]=arguments[i];var u=t.apply(f,n);return"function"!=typeof u&&function(t){throw new Error("[WRONG CONFIGURATION!]: Every key inside the storeActionsConfig must be a higher order function that returns a function \n[".concat(t,"]: key is not a valid function, try something like this: \n{\n\n ").concat(t,": (param) => ({ setState, getState, setMetadata, getMetadata }) => {\n\n setState((state) => ({ ...state, ...param }))\n\n }\n\n}\n"))}(e),u.call(f,{setState:c,getState:l,setMetadata:o,getMetadata:s})},(n=i(n=e))in r?Object.defineProperty(r,n,{value:u,enumerable:!0,configurable:!0,writable:!0}):r[n]=u,r));var r,n,u}),{});return f},this.config=Object.assign({metadata:null},null!=n?n:{}),this.onInitializeStore()}var e,r;return e=t,(r=[{key:"getStateOrchestrator",value:function(t){return this.setterConfig?this.getStoreActionsMap({invokerSetState:t}):this.getSetStateWrapper({invokerSetState:t})}}])&&a(e.prototype,r),Object.defineProperty(e,"prototype",{writable:!1}),t}();e.GlobalStore=l},530:(t,e)=>{"use strict";Object.defineProperty(e,"__esModule",{value:!0})},991:(t,e,r)=>{"use strict";var n=Object.create?function(t,e,r,n){void 0===n&&(n=r);var o=Object.getOwnPropertyDescriptor(e,r);o&&!("get"in o?!e.__esModule:o.writable||o.configurable)||(o={enumerable:!0,get:function(){return e[r]}}),Object.defineProperty(t,n,o)}:function(t,e,r,n){void 0===n&&(n=r),t[n]=e[r]},o=function(t,e){for(var r in t)"default"===r||Object.prototype.hasOwnProperty.call(e,r)||n(e,t,r)};Object.defineProperty(e,"__esModule",{value:!0}),o(r(684),e),o(r(530),e),o(r(774),e)},684:function(t){t.exports=(()=>{"use strict";var t={991:(t,e,r)=>{var n=Object.create?function(t,e,r,n){void 0===n&&(n=r);var o=Object.getOwnPropertyDescriptor(e,r);o&&!("get"in o?!e.__esModule:o.writable||o.configurable)||(o={enumerable:!0,get:function(){return e[r]}}),Object.defineProperty(t,n,o)}:function(t,e,r,n){void 0===n&&(n=r),t[n]=e[r]};Object.defineProperty(e,"__esModule",{value:!0}),function(t,e){for(var r in t)"default"===r||Object.prototype.hasOwnProperty.call(e,r)||n(e,t,r)}(r(729),e)},729:(t,e)=>{function r(t,e){(null==e||e>t.length)&&(e=t.length);for(var r=0,n=new Array(e);r<e;r++)n[r]=t[r];return n}function n(t){return n="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},n(t)}function o(t,e,r){return(e=function(t){var e=function(t,e){if("object"!==n(t)||null===t)return t;var r=t[Symbol.toPrimitive];if(void 0!==r){var o=r.call(t,"string");if("object"!==n(o))return o;throw new TypeError("@@toPrimitive must return a primitive value.")}return String(t)}(t);return"symbol"===n(e)?e:String(e)}(e))in t?Object.defineProperty(t,e,{value:r,enumerable:!0,configurable:!0,writable:!0}):t[e]=r,t}Object.defineProperty(e,"__esModule",{value:!0}),e.formatToStore=e.formatFromStore=e.isPrimitive=e.isRegex=e.isDate=e.isString=e.isBoolean=e.isNumber=e.isNil=e.clone=void 0,e.clone=function(t){if((0,e.isPrimitive)(t)||(0,e.isDate)(t))return t;if(Array.isArray(t))return t.map((function(t){return(0,e.clone)(t)}));if(t instanceof Map){var r=Array.from(t.entries());return new Map(r.map((function(t){return(0,e.clone)(t)})))}if(t instanceof Set){var n=Array.from(t.values());return new Set(n.map((function(t){return(0,e.clone)(t)})))}return t instanceof RegExp?new RegExp(t.toString()):t instanceof Error?new Error(t.message):Object.keys(t).reduce((function(r,n){var a=t[n];return Object.assign(Object.assign({},r),o({},n,(0,e.clone)(a)))}),{})},e.isNil=function(t){return null==t},e.isNumber=function(t){return"number"==typeof t},e.isBoolean=function(t){return"boolean"==typeof t},e.isString=function(t){return"string"==typeof t},e.isDate=function(t){return t instanceof Date},e.isRegex=function(t){return t instanceof RegExp},e.isPrimitive=function(t){return(0,e.isNil)(t)||(0,e.isNumber)(t)||(0,e.isBoolean)(t)||(0,e.isString)(t)||"symbol"===n(t)},e.formatFromStore=function(t){return function(t){var n,a;if((0,e.isPrimitive)(t))return t;if("date"===(null==t?void 0:t.$t))return new Date(t.$v);if("map"===(null==t?void 0:t.$t)){var i=(null!==(n=t.$v)&&void 0!==n?n:[]).map((function(t){var n,o=(2,function(t){if(Array.isArray(t))return t}(n=t)||function(t,e){var r=null==t?null:"undefined"!=typeof Symbol&&t[Symbol.iterator]||t["@@iterator"];if(null!=r){var n,o,a,i,u=[],c=!0,l=!1;try{for(a=(r=r.call(t)).next,0;!(c=(n=a.call(r)).done)&&(u.push(n.value),2!==u.length);c=!0);}catch(t){l=!0,o=t}finally{try{if(!c&&null!=r.return&&(i=r.return(),Object(i)!==i))return}finally{if(l)throw o}}return u}}(n)||function(t,e){if(t){if("string"==typeof t)return r(t,2);var n=Object.prototype.toString.call(t).slice(8,-1);return"Object"===n&&t.constructor&&(n=t.constructor.name),"Map"===n||"Set"===n?Array.from(t):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?r(t,2):void 0}}(n)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()),a=o[0],i=o[1];return[a,(0,e.formatFromStore)(i)]}));return new Map(i)}if("set"===(null==t?void 0:t.$t)){var u=null!==(a=t.$v)&&void 0!==a?a:[].map((function(t){return(0,e.formatFromStore)(t)}));return new Set(u)}return"regex"===(null==t?void 0:t.$t)?new RegExp(t.$v):"error"===(null==t?void 0:t.$t)?new Error(t.$v):Array.isArray(t)?t.map((function(t){return(0,e.formatFromStore)(t)})):Object.keys(t).reduce((function(r,n){var a=t[n];return Object.assign(Object.assign({},r),o({},n,(0,e.formatFromStore)(a)))}),{})}((0,e.clone)(t))},e.formatToStore=function(t){var r,n=(arguments.length>1&&void 0!==arguments[1]?arguments[1]:{stringify:!1}).stringify,a=(r=(0,e.clone)(t),(0,e.isPrimitive)(r)?r:Array.isArray(r)?r.map((function(t){return(0,e.formatToStore)(t)})):r instanceof Map?{$t:"map",$v:Array.from(r.entries()).map((function(t){return(0,e.formatToStore)(t)}))}:r instanceof Set?{$t:"set",$v:Array.from(r.values()).map((function(t){return(0,e.formatToStore)(t)}))}:(0,e.isDate)(r)?{$t:"date",$v:r.toISOString()}:(0,e.isRegex)(r)?{$t:"regex",$v:r.toString()}:r instanceof Error?{$t:"error",$v:r.message}:Object.keys(r).reduce((function(t,n){var a=r[n];return Object.assign(Object.assign({},t),o({},n,(0,e.formatToStore)(a)))}),{}));return n?JSON.stringify(a):a}}},e={};return function r(n){var o=e[n];if(void 0!==o)return o.exports;var a=e[n]={exports:{}};return t[n](a,a.exports,r),a.exports}(991)})()},156:e=>{"use strict";e.exports=t}},r={},function t(n){var o=r[n];if(void 0!==o)return o.exports;var a=r[n]={exports:{}};return e[n].call(a.exports,a,a.exports,t),a.exports}(991);var e,r}));
|
|
1
|
+
!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e(require("react")):"function"==typeof define&&define.amd?define(["react"],e):"object"==typeof exports?exports["react-native-global-state-hooks"]=e(require("react")):t["react-native-global-state-hooks"]=e(t.react)}(this,(t=>{return e={774:(t,e,r)=>{"use strict";function n(t){return n="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},n(t)}function o(t,e){(null==e||e>t.length)&&(e=t.length);for(var r=0,n=new Array(e);r<e;r++)n[r]=t[r];return n}function i(t,e){for(var r=0;r<e.length;r++){var n=e[r];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(t,a(n.key),n)}}function a(t){var e=function(t,e){if("object"!==n(t)||null===t)return t;var r=t[Symbol.toPrimitive];if(void 0!==r){var o=r.call(t,"string");if("object"!==n(o))return o;throw new TypeError("@@toPrimitive must return a primitive value.")}return String(t)}(t);return"symbol"===n(e)?e:String(e)}Object.defineProperty(e,"__esModule",{value:!0}),e.createGlobalHook=e.GlobalStore=void 0;var u=r(156),c=function(){function t(e){var r=this,n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},i=arguments.length>2&&void 0!==arguments[2]?arguments[2]:null;!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,t),this.setterConfig=i,this.subscribers=new Set,this.config={metadata:null},this.onInit=null,this.onStateChanged=null,this.onSubscribed=null,this.computePreventStateChange=null,this.initialize=function(){var t=r.onInit,e=r.config.onInit;if(t||e){var n=r.getConfigCallbackParam({});null==t||t(n),null==e||e(n)}},this.setState=function(t){var e=t.invokerSetState,n=t.state;r.stateWrapper={state:n},null==e||e({state:n}),r.subscribers.forEach((function(t){t!==e&&t({state:n})}))},this.setMetadata=function(t){var e,n,o="function"==typeof t?t(null!==(e=r.config.metadata)&&void 0!==e?e:null):t;r.config=Object.assign(Object.assign({},null!==(n=r.config)&&void 0!==n?n:{}),{metadata:o})},this.getConfigCallbackParam=function(t){var e=t.invokerSetState;return{setMetadata:r.setMetadata,getMetadata:function(){return r.config.metadata},getState:function(){return r.stateWrapper.state},setState:r.getSetStateWrapper({invokerSetState:e}),actions:r.getStoreActionsMap()}},this.getHook=function(){return function(){var t,e,n=(t=(0,u.useState)((function(){return r.stateWrapper})),e=2,function(t){if(Array.isArray(t))return t}(t)||function(t,e){var r=null==t?null:"undefined"!=typeof Symbol&&t[Symbol.iterator]||t["@@iterator"];if(null!=r){var n,o,i,a,u=[],c=!0,f=!1;try{if(i=(r=r.call(t)).next,0===e){if(Object(r)!==r)return;c=!1}else for(;!(c=(n=i.call(r)).done)&&(u.push(n.value),u.length!==e);c=!0);}catch(t){f=!0,o=t}finally{try{if(!c&&null!=r.return&&(a=r.return(),Object(a)!==a))return}finally{if(f)throw o}}return u}}(t,e)||function(t,e){if(t){if("string"==typeof t)return o(t,e);var r=Object.prototype.toString.call(t).slice(8,-1);return"Object"===r&&t.constructor&&(r=t.constructor.name),"Map"===r||"Set"===r?Array.from(t):"Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r)?o(t,e):void 0}}(t,e)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()),i=n[0],a=n[1];(0,u.useEffect)((function(){r.subscribers.add(a);var t=r.onSubscribed,e=r.config.onSubscribed;if(t||e){var n=r.getConfigCallbackParam({invokerSetState:a});null==t||t(n),null==e||e(n)}return function(){r.subscribers.delete(a)}}),[]);var c=r.getStateOrchestrator(a);return[i.state,c,r.config.metadata]}},this.getHookDecoupled=function(){return[function(){return r.stateWrapper.state},r.getStateOrchestrator(),function(){return r.config.metadata}]},this.getSetStateWrapper=function(){var t=(arguments.length>0&&void 0!==arguments[0]?arguments[0]:{}).invokerSetState;return function(e){var n=(arguments.length>1&&void 0!==arguments[1]?arguments[1]:{}).forceUpdate;r.computeSetState({invokerSetState:t,setter:e,forceUpdate:n})}},this.hasStateCallbacks=function(){var t=r.computePreventStateChange,e=r.onStateChanged,n=r.config,o=n.computePreventStateChange,i=n.onStateChanged;return!!(t||o||e||i)},this.computeSetState=function(t){var e=t.setter,n=t.invokerSetState,o=t.forceUpdate,i="function"==typeof e,a=r.stateWrapper.state,u=i?e(a):e;if(o||!Object.is(r.stateWrapper.state,u)){var c=r.hasStateCallbacks(),f=c&&r.getStoreActionsMap({}),s=c&&r.getSetStateWrapper({invokerSetState:n}),l={setMetadata:r.setMetadata,getMetadata:function(){return r.config.metadata},setState:s,getState:function(){return r.stateWrapper.state},actions:f,previousState:a,state:u},p=r.computePreventStateChange,v=r.config.computePreventStateChange;if((p||v)&&((null==p?void 0:p(l))||(null==v?void 0:v(l))))return;r.setState({invokerSetState:n,state:u});var y=r.onStateChanged,b=r.config.onStateChanged;(y||b)&&(null==y||y(l),null==b||b(l))}},this.getStoreActionsMap=function(){var t=(arguments.length>0&&void 0!==arguments[0]?arguments[0]:{}).invokerSetState;if(!r.setterConfig)return null;var e=r.setterConfig,n=r.setMetadata,o=e,i=Object.keys(o),u=r.getSetStateWrapper({invokerSetState:t}),c=function(){return r.stateWrapper.state},f=function(){return r.config.metadata},s=i.reduce((function(t,e){return Object.assign(Object.assign({},t),(r={},l=function(){for(var t=o[e],r=arguments.length,i=new Array(r),a=0;a<r;a++)i[a]=arguments[a];var l=t.apply(s,i);return"function"!=typeof l&&function(t){throw new Error("[WRONG CONFIGURATION!]: Every key inside the storeActionsConfig must be a higher order function that returns a function \n[".concat(t,"]: key is not a valid function, try something like this: \n{\n\n ").concat(t,": (param) => ({ setState, getState, setMetadata, getMetadata }) => {\n\n setState((state) => ({ ...state, ...param }))\n\n }\n\n}\n"))}(e),l.call(s,{setState:u,getState:c,setMetadata:n,getMetadata:f,actions:s})},(i=a(i=e))in r?Object.defineProperty(r,i,{value:l,enumerable:!0,configurable:!0,writable:!0}):r[i]=l,r));var r,i,l}),{});return s},this.stateWrapper={state:e},this.config=Object.assign({metadata:null},null!=n?n:{}),this.constructor!==t||this.initialize()}var e,r;return e=t,(r=[{key:"state",get:function(){return this.stateWrapper.state}},{key:"getStateOrchestrator",value:function(t){return this.setterConfig?this.getStoreActionsMap({invokerSetState:t}):this.getSetStateWrapper({invokerSetState:t})}}])&&i(e.prototype,r),Object.defineProperty(e,"prototype",{writable:!1}),t}();e.GlobalStore=c,e.createGlobalHook=function(t){return new c(t,arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},arguments.length>2&&void 0!==arguments[2]?arguments[2]:null).getHook()}},530:(t,e)=>{"use strict";Object.defineProperty(e,"__esModule",{value:!0})},195:(t,e,r)=>{"use strict";function n(t){return n="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},n(t)}function o(t,e){return o=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(t,e){return t.__proto__=e,t},o(t,e)}function i(t){return i=Object.setPrototypeOf?Object.getPrototypeOf.bind():function(t){return t.__proto__||Object.getPrototypeOf(t)},i(t)}Object.defineProperty(e,"__esModule",{value:!0}),e.GlobalStoreAbstract=void 0;var a=function(t){!function(t,e){if("function"!=typeof e&&null!==e)throw new TypeError("Super expression must either be null or a function");t.prototype=Object.create(e&&e.prototype,{constructor:{value:t,writable:!0,configurable:!0}}),Object.defineProperty(t,"prototype",{writable:!1}),e&&o(t,e)}(c,t);var e,r,a,u=(r=c,a=function(){if("undefined"==typeof Reflect||!Reflect.construct)return!1;if(Reflect.construct.sham)return!1;if("function"==typeof Proxy)return!0;try{return Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],(function(){}))),!0}catch(t){return!1}}(),function(){var t,e=i(r);if(a){var o=i(this).constructor;t=Reflect.construct(e,arguments,o)}else t=e.apply(this,arguments);return function(t,e){if(e&&("object"===n(e)||"function"==typeof e))return e;if(void 0!==e)throw new TypeError("Derived constructors may only return object or undefined");return function(t){if(void 0===t)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return t}(t)}(this,t)});function c(t){var e,r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:null;return function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,c),(e=u.call(this,t,r,n)).onInit=function(t){e.onInitialize(t)},e.onStateChanged=function(t){e.onChange(t)},e}return e=c,Object.defineProperty(e,"prototype",{writable:!1}),e}(r(774).GlobalStore);e.GlobalStoreAbstract=a},991:(t,e,r)=>{"use strict";var n=Object.create?function(t,e,r,n){void 0===n&&(n=r);var o=Object.getOwnPropertyDescriptor(e,r);o&&!("get"in o?!e.__esModule:o.writable||o.configurable)||(o={enumerable:!0,get:function(){return e[r]}}),Object.defineProperty(t,n,o)}:function(t,e,r,n){void 0===n&&(n=r),t[n]=e[r]},o=function(t,e){for(var r in t)"default"===r||Object.prototype.hasOwnProperty.call(e,r)||n(e,t,r)};Object.defineProperty(e,"__esModule",{value:!0}),o(r(684),e),o(r(530),e),o(r(774),e),o(r(195),e)},684:function(t){t.exports=(()=>{"use strict";var t={991:(t,e,r)=>{var n=Object.create?function(t,e,r,n){void 0===n&&(n=r);var o=Object.getOwnPropertyDescriptor(e,r);o&&!("get"in o?!e.__esModule:o.writable||o.configurable)||(o={enumerable:!0,get:function(){return e[r]}}),Object.defineProperty(t,n,o)}:function(t,e,r,n){void 0===n&&(n=r),t[n]=e[r]};Object.defineProperty(e,"__esModule",{value:!0}),function(t,e){for(var r in t)"default"===r||Object.prototype.hasOwnProperty.call(e,r)||n(e,t,r)}(r(729),e)},729:(t,e)=>{function r(t){return r="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t},r(t)}function n(t,e,n){return(e=function(t){var e=function(t,e){if("object"!==r(t)||null===t)return t;var n=t[Symbol.toPrimitive];if(void 0!==n){var o=n.call(t,"string");if("object"!==r(o))return o;throw new TypeError("@@toPrimitive must return a primitive value.")}return String(t)}(t);return"symbol"===r(e)?e:String(e)}(e))in t?Object.defineProperty(t,e,{value:n,enumerable:!0,configurable:!0,writable:!0}):t[e]=n,t}function o(t,e){if(t){if("string"==typeof t)return i(t,e);var r=Object.prototype.toString.call(t).slice(8,-1);return"Object"===r&&t.constructor&&(r=t.constructor.name),"Map"===r||"Set"===r?Array.from(t):"Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r)?i(t,e):void 0}}function i(t,e){(null==e||e>t.length)&&(e=t.length);for(var r=0,n=new Array(e);r<e;r++)n[r]=t[r];return n}Object.defineProperty(e,"__esModule",{value:!0}),e.formatToStore=e.formatFromStore=e.isPrimitive=e.isFunction=e.isRegex=e.isDate=e.isString=e.isBoolean=e.isNumber=e.isNil=e.clone=void 0,e.clone=function(t){var r,a=(arguments.length>1&&void 0!==arguments[1]?arguments[1]:{}).shallow;if((0,e.isPrimitive)(t)||(0,e.isDate)(t))return t;if(Array.isArray(t))return a?function(t){if(Array.isArray(t))return i(t)}(r=t)||function(t){if("undefined"!=typeof Symbol&&null!=t[Symbol.iterator]||null!=t["@@iterator"])return Array.from(t)}(r)||o(r)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}():t.map((function(t){return(0,e.clone)(t)}));if(t instanceof Map){var u=Array.from(t.entries());return a?new Map(u):new Map(u.map((function(t){return(0,e.clone)(t)})))}if(t instanceof Set){var c=Array.from(t.values());return a?new Set(c):new Set(c.map((function(t){return(0,e.clone)(t)})))}return t instanceof RegExp?new RegExp(t.toString()):(0,e.isFunction)(t)?a?t:Object.create(t):a?Object.assign({},t):t instanceof Error?new Error(t.message):Object.keys(t).reduce((function(r,o){var i=t[o];return Object.assign(Object.assign({},r),n({},o,(0,e.clone)(i)))}),{})},e.isNil=function(t){return null==t},e.isNumber=function(t){return"number"==typeof t},e.isBoolean=function(t){return"boolean"==typeof t},e.isString=function(t){return"string"==typeof t},e.isDate=function(t){return t instanceof Date},e.isRegex=function(t){return t instanceof RegExp},e.isFunction=function(t){return"function"==typeof t||t instanceof Function},e.isPrimitive=function(t){return(0,e.isNil)(t)||(0,e.isNumber)(t)||(0,e.isBoolean)(t)||(0,e.isString)(t)||"symbol"===r(t)},e.formatFromStore=function(t){return function(t){var r,i;if((0,e.isPrimitive)(t))return t;if("date"===(null==t?void 0:t.$t))return new Date(t.$v);if("map"===(null==t?void 0:t.$t)){var a=(null!==(r=t.$v)&&void 0!==r?r:[]).map((function(t){var r,n=(2,function(t){if(Array.isArray(t))return t}(r=t)||function(t,e){var r=null==t?null:"undefined"!=typeof Symbol&&t[Symbol.iterator]||t["@@iterator"];if(null!=r){var n,o,i,a,u=[],c=!0,f=!1;try{for(i=(r=r.call(t)).next,0;!(c=(n=i.call(r)).done)&&(u.push(n.value),2!==u.length);c=!0);}catch(t){f=!0,o=t}finally{try{if(!c&&null!=r.return&&(a=r.return(),Object(a)!==a))return}finally{if(f)throw o}}return u}}(r)||o(r,2)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()),i=n[0],a=n[1];return[i,(0,e.formatFromStore)(a)]}));return new Map(a)}if("set"===(null==t?void 0:t.$t)){var u=null!==(i=t.$v)&&void 0!==i?i:[].map((function(t){return(0,e.formatFromStore)(t)}));return new Set(u)}return"regex"===(null==t?void 0:t.$t)?new RegExp(t.$v):"error"===(null==t?void 0:t.$t)?new Error(t.$v):Array.isArray(t)?t.map((function(t){return(0,e.formatFromStore)(t)})):"function"===(null==t?void 0:t.$t)?Function("(".concat(t.$v,")(...arguments)")):Object.keys(t).reduce((function(r,o){var i=t[o];return Object.assign(Object.assign({},r),n({},o,(0,e.formatFromStore)(i)))}),{})}((arguments.length>1&&void 0!==arguments[1]?arguments[1]:{}).jsonParse?JSON.parse(t):(0,e.clone)(t))},e.formatToStore=function(t){var o=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{stringify:!1},i=o.stringify,a=o.validator,u=o.excludeTypes,c=o.excludeKeys,f=new Set(null!=u?u:[]),s=new Set(null!=c?c:[]),l=f.size||s.size,p=null!=a?a:function(t){var e=t.key,n=t.value;if(!l)return!0;var o=s.has(e),i=f.has(r(n));return!o&&!i},v=function t(r){if((0,e.isPrimitive)(r))return r;if(Array.isArray(r))return r.map((function(e){return t(e)}));if(r instanceof Map)return{$t:"map",$v:Array.from(r.entries()).map((function(e){return t(e)}))};if(r instanceof Set)return{$t:"set",$v:Array.from(r.values()).map((function(e){return t(e)}))};if((0,e.isDate)(r))return{$t:"date",$v:r.toISOString()};if((0,e.isRegex)(r))return{$t:"regex",$v:r.toString()};if((0,e.isFunction)(r)){var o;try{o={$t:"function",$v:r.toString()}}catch(t){o={$t:"error",$v:"Error: Could not serialize function"}}return o}return r instanceof Error?{$t:"error",$v:r.message}:Object.keys(r).reduce((function(e,o){var i=r[o],a=t(i);return p({obj:r,key:o,value:a})?Object.assign(Object.assign({},e),n({},o,t(i))):e}),{})}((0,e.clone)(t));return i?JSON.stringify(v):v}}},e={};return function r(n){var o=e[n];if(void 0!==o)return o.exports;var i=e[n]={exports:{}};return t[n](i,i.exports,r),i.exports}(991)})()},156:e=>{"use strict";e.exports=t}},r={},function t(n){var o=r[n];if(void 0!==o)return o.exports;var i=r[n]={exports:{}};return e[n].call(i.exports,i,i.exports,t),i.exports}(991);var e,r}));
|
package/lib/index.d.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native-global-state-hooks",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.7",
|
|
4
4
|
"description": "This is a package to easily handling global-state across your react-native-components No-redux",
|
|
5
5
|
"main": "lib/bundle.js",
|
|
6
6
|
"types": "lib/index.d.ts",
|
|
@@ -80,6 +80,6 @@
|
|
|
80
80
|
}
|
|
81
81
|
},
|
|
82
82
|
"dependencies": {
|
|
83
|
-
"json-storage-formatter": "^1.0.
|
|
83
|
+
"json-storage-formatter": "^1.0.8"
|
|
84
84
|
}
|
|
85
85
|
}
|
package/README.advance.md
DELETED
|
@@ -1,123 +0,0 @@
|
|
|
1
|
-
## Creating hooks with reusable actions
|
|
2
|
-
|
|
3
|
-
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**:
|
|
4
|
-
|
|
5
|
-
```JSX
|
|
6
|
-
import {
|
|
7
|
-
IActionCollectionConfig,
|
|
8
|
-
IActionCollectionResult,
|
|
9
|
-
StateSetter,
|
|
10
|
-
} from 'react-native-global-state-hooks/lib/GlobalStoreTypes';
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* When using a custom api, the getHook and getHookDecoupled will not longer return directly the setter,
|
|
14
|
-
* intead they will return and api with the specific actions and mutations defined for the store
|
|
15
|
-
* Creating a configuration object for our api
|
|
16
|
-
*/
|
|
17
|
-
const countActionsApi: IActionCollectionConfig<number> = {
|
|
18
|
-
/* Decrease the value of the count */
|
|
19
|
-
decrease(decrease: number) {
|
|
20
|
-
/**
|
|
21
|
-
* We need to return the async function that is gonna take care of the state mutation or actions
|
|
22
|
-
*/
|
|
23
|
-
return async (setter: StateSetter<number>, state: number) => {
|
|
24
|
-
/**
|
|
25
|
-
* Next, we perfom whatever modification we want on top of the store
|
|
26
|
-
*/
|
|
27
|
-
return setter(state - decrease);
|
|
28
|
-
};
|
|
29
|
-
},
|
|
30
|
-
|
|
31
|
-
//* Lets add a new action to increase the value of the count */
|
|
32
|
-
increase(increase: number) {
|
|
33
|
-
|
|
34
|
-
return async (setter: StateSetter<number>, state: number) => {
|
|
35
|
-
return setter(state + increase);
|
|
36
|
-
};
|
|
37
|
-
},
|
|
38
|
-
};
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* Now our getHook and getHookDecoupled are gonna return our custom api instead of the StateSetter,
|
|
42
|
-
* This will allow us to have more control over our store since the mutations of the same are gonna be limitated
|
|
43
|
-
*/
|
|
44
|
-
const countStore = new GlobalStore(0, countActionsApi);
|
|
45
|
-
```
|
|
46
|
-
|
|
47
|
-
If we remove all the explanatory comments the code will look like this:
|
|
48
|
-
|
|
49
|
-
```TS
|
|
50
|
-
const countStore = new GlobalStore(0, {
|
|
51
|
-
decrease(decrease: number) {
|
|
52
|
-
return (setter: StateSetter<number>, state: number) =>
|
|
53
|
-
setter(state - decrease);
|
|
54
|
-
},
|
|
55
|
-
|
|
56
|
-
increase(increase: number) {
|
|
57
|
-
return (setter: StateSetter<number>, state: number) =>
|
|
58
|
-
setter(state + increase);
|
|
59
|
-
},
|
|
60
|
-
} as IActionCollectionConfig<number>);
|
|
61
|
-
```
|
|
62
|
-
|
|
63
|
-
Now lets get our new global hook with specific API
|
|
64
|
-
|
|
65
|
-
```TS
|
|
66
|
-
export interface ICountActions
|
|
67
|
-
extends IActionCollectionResult<number, IActionCollectionConfig<number>> {
|
|
68
|
-
decrease: (decrease: number) => Promise<number>;
|
|
69
|
-
increase: (increase: number) => Promise<number>;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
/**
|
|
73
|
-
* 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
|
|
74
|
-
*/
|
|
75
|
-
export const useCountGlobal = countStore.getHook<ICountActions>();
|
|
76
|
-
```
|
|
77
|
-
|
|
78
|
-
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:
|
|
79
|
-
|
|
80
|
-
```JSX
|
|
81
|
-
import { useCountGlobal } from './useCountGlobal'
|
|
82
|
-
|
|
83
|
-
const MyComponent: Reac.FC = () => {
|
|
84
|
-
const [count, countActions] = useCountGlobal();
|
|
85
|
-
|
|
86
|
-
// this functions are strongly typed
|
|
87
|
-
const increaseClick = () => countActions.increase(1);
|
|
88
|
-
const decreaseClick = () => countActions.decrease(1);
|
|
89
|
-
|
|
90
|
-
return (<>
|
|
91
|
-
<Text>{count}<Text/>
|
|
92
|
-
<Button onPress={increaseClick} title={'increase'} />
|
|
93
|
-
<Button onPress={decreaseClick} title={'decrease'} />
|
|
94
|
-
</>);
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
```
|
|
98
|
-
|
|
99
|
-
## Customize persist storage
|
|
100
|
-
|
|
101
|
-
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.
|
|
102
|
-
|
|
103
|
-
```JSX
|
|
104
|
-
import GlobalState from 'react-native-global-state-hooks';
|
|
105
|
-
import secureStorage from 'react-native-secure-storage';
|
|
106
|
-
import { IActionCollection } from 'react-native-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 asyncStorageGetItem = () => secureStorage.getItem(this.persistStoreAs as string, config);
|
|
116
|
-
|
|
117
|
-
/** value is a json string*/
|
|
118
|
-
protected asyncStorageSetItem = (value: string) => secureStorage.setItem(this.persistStoreAs as string, value, config);
|
|
119
|
-
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
export default SecureGlobalState;
|
|
123
|
-
```
|