react-native-global-state-hooks 2.0.7 → 2.1.1
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 +324 -60
- package/lib/GlobalStore.d.ts +160 -48
- package/lib/GlobalStore.d.ts.map +1 -1
- package/lib/GlobalStore.js +275 -134
- package/lib/GlobalStore.types.d.ts +108 -0
- package/lib/GlobalStore.types.d.ts.map +1 -0
- package/lib/{GlobalStoreTypes.js → GlobalStore.types.js} +0 -0
- package/lib/GlobalStore.utils.d.ts +3 -0
- package/lib/GlobalStore.utils.d.ts.map +1 -0
- package/lib/GlobalStore.utils.js +5 -0
- package/lib/index.d.ts +4 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +6 -0
- package/package.json +4 -5
- package/lib/GlobalStoreTypes.d.ts +0 -66
- package/lib/GlobalStoreTypes.d.ts.map +0 -1
package/lib/GlobalStore.js
CHANGED
|
@@ -1,167 +1,308 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.GlobalStore =
|
|
4
|
-
const tslib_1 = require("tslib");
|
|
3
|
+
exports.GlobalStore = void 0;
|
|
5
4
|
const react_1 = require("react");
|
|
6
|
-
const
|
|
7
|
-
const
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
callback(...args);
|
|
14
|
-
}, wait);
|
|
15
|
-
});
|
|
5
|
+
const GlobalStore_utils_1 = require("./GlobalStore.utils");
|
|
6
|
+
const throwWrongKeyOnActionCollectionConfig = (action_key) => {
|
|
7
|
+
throw new Error(`[WRONG CONFIGURATION!]: Every key inside the storeActionsConfig must be a higher order function that returns a function \n[${action_key}]: key is not a valid function, try something like this: \n{\n
|
|
8
|
+
${action_key}: (param) => ({ setState, getState, setMetadata, getMetadata }) => {\n
|
|
9
|
+
setState((state) => ({ ...state, ...param }))\n
|
|
10
|
+
}\n
|
|
11
|
+
}\n`);
|
|
16
12
|
};
|
|
17
|
-
|
|
13
|
+
/**
|
|
14
|
+
* The GlobalStore class is the main class of the library and it is used to create a GlobalStore instances
|
|
15
|
+
* @template {TState} TState - The type of the state object
|
|
16
|
+
* @template {TMetadata} TMetadata - The type of the metadata object (optional) (default: null) no reactive information set to share with the subscribers
|
|
17
|
+
* @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
|
|
18
|
+
* */
|
|
18
19
|
class GlobalStore {
|
|
19
|
-
get isPersistStore() {
|
|
20
|
-
return !!this.persistStoreAs;
|
|
21
|
-
}
|
|
22
|
-
constructor(state, actions = null, persistStoreAs = null,
|
|
23
20
|
/**
|
|
24
|
-
*
|
|
25
|
-
|
|
26
|
-
|
|
21
|
+
* Create a new instance of the GlobalStore
|
|
22
|
+
* @param {TState} state - The initial state
|
|
23
|
+
* @param {TMetadata} metadata - The metadata object (optional) (default: null) no reactive information set to share with the subscribers
|
|
24
|
+
* @param {TStateSetter} setterConfig - The actions configuration object (optional) (default: null) if not null the store manipulation will be done through the actions
|
|
25
|
+
* @param {GlobalStoreConfig<TState, TMetadata>} config - The configuration object (optional) (default: { metadata: null })
|
|
26
|
+
* @param {StateConfigCallbackParam<TState, TMetadata>} config.onInit - The callback to execute when the store is initialized (optional) (default: null)
|
|
27
|
+
* @param {StateConfigCallbackParam<TState, TMetadata>} config.onStateChanged - The callback to execute when the state is changed (optional) (default: null)
|
|
28
|
+
* @param {StateConfigCallbackParam<TState, TMetadata>} config.onSubscribed - The callback to execute when a subscriber is added (optional) (default: null)
|
|
29
|
+
* @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)
|
|
30
|
+
* */
|
|
31
|
+
constructor(state, metadata = null, setterConfig = null, config = {}) {
|
|
27
32
|
this.state = state;
|
|
28
|
-
this.
|
|
29
|
-
this.
|
|
30
|
-
this.
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
33
|
+
this.metadata = metadata;
|
|
34
|
+
this.setterConfig = setterConfig;
|
|
35
|
+
this.config = config;
|
|
36
|
+
/**
|
|
37
|
+
* list of all the subscribers setState functions
|
|
38
|
+
* @template {TState} TState - The type of the state object
|
|
39
|
+
* */
|
|
40
|
+
this.subscribers = new Set();
|
|
41
|
+
/**
|
|
42
|
+
* execute once the store is created
|
|
43
|
+
* @template {TState} TState - The type of the state object
|
|
44
|
+
* @template {TMetadata} TMetadata - The type of the metadata object (optional) (default: null) no reactive information set to share with the subscribers
|
|
45
|
+
* @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
|
|
46
|
+
* @param {StateConfigCallbackParam<TState, TMetadata, TStateSetter>} parameters - The parameters object brings the following properties: setState, getState, setMetadata, getMetadata
|
|
47
|
+
* @param {Dispatch<SetStateAction<TState>>} parameters.setState - The setState function to update the state
|
|
48
|
+
* @param {() => TState} parameters.getState - The getState function to get the state
|
|
49
|
+
* @param {Dispatch<SetStateAction<TMetadata>>} parameters.setMetadata - The setMetadata function to update the metadata
|
|
50
|
+
* @param {() => TMetadata} parameters.getMetadata - The getMetadata function to get the metadata
|
|
51
|
+
* */
|
|
52
|
+
this.onInit = null;
|
|
53
|
+
/**
|
|
54
|
+
* execute every time the state is changed
|
|
55
|
+
* @template {TState} TState - The type of the state object
|
|
56
|
+
* @template {TMetadata} TMetadata - The type of the metadata object (optional) (default: null) no reactive information set to share with the subscribers
|
|
57
|
+
* @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
|
|
58
|
+
* @param {StateConfigCallbackParam<TState, TMetadata, TStateSetter>} parameters - The parameters object brings the following properties: setState, getState, setMetadata, getMetadata
|
|
59
|
+
* @param {Dispatch<SetStateAction<TState>>} parameters.setState - The setState function to update the state
|
|
60
|
+
* @param {() => TState} parameters.getState - The getState function to get the state
|
|
61
|
+
* @param {Dispatch<SetStateAction<TMetadata>>} parameters.setMetadata - The setMetadata function to update the metadata
|
|
62
|
+
* @param {() => TMetadata} parameters.getMetadata - The getMetadata function to get the metadata
|
|
63
|
+
* */
|
|
64
|
+
this.onStateChanged = null;
|
|
65
|
+
/**
|
|
66
|
+
* Execute each time a new component gets subscribed to the store
|
|
67
|
+
* @template {TState} TState - The type of the state object
|
|
68
|
+
* @template {TMetadata} TMetadata - The type of the metadata object (optional) (default: null) no reactive information set to share with the subscribers
|
|
69
|
+
* @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
|
|
70
|
+
* @param {StateConfigCallbackParam<TState, TMetadata, TStateSetter>} parameters - The parameters object brings the following properties: setState, getState, setMetadata, getMetadata
|
|
71
|
+
* @param {Dispatch<SetStateAction<TState>>} parameters.setState - The setState function to update the state
|
|
72
|
+
* @param {() => TState} parameters.getState - The getState function to get the state
|
|
73
|
+
* @param {Dispatch<SetStateAction<TMetadata>>} parameters.setMetadata - The setMetadata function to update the metadata
|
|
74
|
+
* @param {() => TMetadata} parameters.getMetadata - The getMetadata function to get the metadata
|
|
75
|
+
* */
|
|
76
|
+
this.onSubscribed = null;
|
|
77
|
+
/**
|
|
78
|
+
* Execute everytime a state change is triggered and before the state is updated, it allows to prevent the state change by returning true
|
|
79
|
+
* @template {TState} TState - The type of the state object
|
|
80
|
+
* @template {TMetadata} TMetadata - The type of the metadata object (optional) (default: null) no reactive information set to share with the subscribers
|
|
81
|
+
* @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
|
|
82
|
+
* @param {StateConfigCallbackParam<TState, TMetadata, TStateSetter>} parameters - The parameters object brings the following properties: setState, getState, setMetadata, getMetadata
|
|
83
|
+
* @param {Dispatch<SetStateAction<TState>>} parameters.setState - The setState function to update the state
|
|
84
|
+
* @param {() => TState} parameters.getState - The getState function to get the state
|
|
85
|
+
* @param {Dispatch<SetStateAction<TMetadata>>} parameters.setMetadata - The setMetadata function to update the metadata
|
|
86
|
+
* @param {() => TMetadata} parameters.getMetadata - The getMetadata function to get the metadata
|
|
87
|
+
* @returns {boolean} - true to prevent the state change, false to allow the state change
|
|
88
|
+
* */
|
|
89
|
+
this.computePreventStateChange = null;
|
|
90
|
+
this.onInitializeStore = () => {
|
|
91
|
+
const { onInit } = this;
|
|
92
|
+
const { onInit: onInitFromConfig } = this.config;
|
|
93
|
+
if (!onInit && !onInitFromConfig)
|
|
94
|
+
return;
|
|
95
|
+
const parameters = this.getConfigCallbackParam({});
|
|
96
|
+
onInit === null || onInit === void 0 ? void 0 : onInit(parameters);
|
|
97
|
+
onInitFromConfig === null || onInitFromConfig === void 0 ? void 0 : onInitFromConfig(parameters);
|
|
98
|
+
};
|
|
99
|
+
/**
|
|
100
|
+
* gets a clone of the state
|
|
101
|
+
* @returns {TState} - The state clone
|
|
102
|
+
* */
|
|
103
|
+
this.getStateClone = () => (0, GlobalStore_utils_1.clone)(this.state);
|
|
104
|
+
/**
|
|
105
|
+
* gets a clone of the metadata
|
|
106
|
+
* @returns {TMetadata} - The metadata clone
|
|
107
|
+
* */
|
|
108
|
+
this.getMetadataClone = () => (0, GlobalStore_utils_1.clone)(this.metadata);
|
|
109
|
+
/**
|
|
110
|
+
* set the state and update all the subscribers
|
|
111
|
+
* @param {StateSetter<TState>} setter - The setter function or the value to set
|
|
112
|
+
* @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
|
|
113
|
+
* */
|
|
114
|
+
this.setState = ({ invokerSetState, state, }) => {
|
|
115
|
+
// update the state
|
|
116
|
+
this.state = state;
|
|
117
|
+
// execute first the callback of the component that invoked the state change
|
|
118
|
+
invokerSetState === null || invokerSetState === void 0 ? void 0 : invokerSetState(state);
|
|
119
|
+
// update all the subscribers
|
|
120
|
+
this.subscribers.forEach((setState) => {
|
|
121
|
+
if (setState === invokerSetState)
|
|
122
|
+
return;
|
|
123
|
+
setState(state);
|
|
124
|
+
});
|
|
125
|
+
};
|
|
126
|
+
/**
|
|
127
|
+
* Set the value of the metadata property, this is no reactive and will not trigger a re-render
|
|
128
|
+
* @param {StateSetter<TMetadata>} setter - The setter function or the value to set
|
|
129
|
+
* */
|
|
130
|
+
this.setMetadata = (setter) => {
|
|
131
|
+
const isSetterFunction = typeof setter === 'function';
|
|
132
|
+
const metadata = isSetterFunction
|
|
133
|
+
? setter(this.getMetadataClone())
|
|
134
|
+
: setter;
|
|
135
|
+
this.metadata = metadata;
|
|
136
|
+
};
|
|
137
|
+
/**
|
|
138
|
+
* get the parameters object to pass to the callback functions (onInit, onStateChanged, onSubscribed, computePreventStateChange)
|
|
139
|
+
* this parameters object brings the following properties: setState, getState, setMetadata, getMetadata
|
|
140
|
+
* this parameter object allows to update the state, get the state, update the metadata, get the metadata
|
|
141
|
+
* @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
|
|
142
|
+
* @returns {StateConfigCallbackParam<TState, TMetadata>} - The parameters object
|
|
143
|
+
* */
|
|
144
|
+
this.getConfigCallbackParam = ({ invokerSetState, }) => {
|
|
145
|
+
const { setMetadata, getMetadataClone: getMetadata, getStateClone: getState, } = this;
|
|
146
|
+
const setState = this.getSetStateWrapper({ invokerSetState });
|
|
147
|
+
const actions = this.getStoreActionsMap({});
|
|
148
|
+
return {
|
|
149
|
+
setMetadata,
|
|
150
|
+
getMetadata,
|
|
151
|
+
getState,
|
|
152
|
+
setState,
|
|
153
|
+
actions,
|
|
154
|
+
};
|
|
155
|
+
};
|
|
156
|
+
/**
|
|
157
|
+
* Returns a custom hook that allows to handle a global state
|
|
158
|
+
* @returns {[TState, TStateSetter, TMetadata]} - The state, the state setter or the actions map, the metadata
|
|
159
|
+
* */
|
|
35
160
|
this.getHook = () => () => {
|
|
36
161
|
const [value, invokerSetState] = (0, react_1.useState)(() => this.state);
|
|
37
162
|
(0, react_1.useEffect)(() => {
|
|
38
|
-
this.subscribers.
|
|
39
|
-
|
|
40
|
-
|
|
163
|
+
this.subscribers.add(invokerSetState);
|
|
164
|
+
const { onSubscribed } = this;
|
|
165
|
+
const { onSubscribed: onSubscribedFromConfig } = this.config;
|
|
166
|
+
if (onSubscribed || onSubscribedFromConfig) {
|
|
167
|
+
const parameters = this.getConfigCallbackParam({ invokerSetState });
|
|
168
|
+
onSubscribed === null || onSubscribed === void 0 ? void 0 : onSubscribed(parameters);
|
|
169
|
+
onSubscribedFromConfig === null || onSubscribedFromConfig === void 0 ? void 0 : onSubscribedFromConfig(parameters);
|
|
41
170
|
}
|
|
42
171
|
return () => {
|
|
43
|
-
this.subscribers
|
|
172
|
+
this.subscribers.delete(invokerSetState);
|
|
44
173
|
};
|
|
45
174
|
}, []);
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
this.getStateOrchestrator(invokerSetState),
|
|
49
|
-
this.isStoredStateItemUpdated,
|
|
50
|
-
];
|
|
175
|
+
const stateOrchestrator = this.getStateOrchestrator(invokerSetState);
|
|
176
|
+
return [value, stateOrchestrator, this.getMetadataClone()];
|
|
51
177
|
};
|
|
178
|
+
/**
|
|
179
|
+
* Returns an array with the a function to get the state, the state setter or the actions map, and a function to get the metadata
|
|
180
|
+
* @returns {[() => TState, TStateSetter, () => TMetadata]} - The state getter, the state setter or the actions map, the metadata getter
|
|
181
|
+
* */
|
|
52
182
|
this.getHookDecoupled = () => {
|
|
53
|
-
const getState
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
}
|
|
57
|
-
return this.state;
|
|
58
|
-
};
|
|
59
|
-
return [
|
|
60
|
-
getState,
|
|
61
|
-
this.getStateOrchestrator(),
|
|
62
|
-
];
|
|
183
|
+
const { getStateClone: getState, getMetadataClone: getMetadata } = this;
|
|
184
|
+
const stateOrchestrator = this.getStateOrchestrator();
|
|
185
|
+
return [getState, stateOrchestrator, getMetadata];
|
|
63
186
|
};
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
return (setter) => {
|
|
73
|
-
stateOrchestrator({ invokerSetState, setter });
|
|
187
|
+
/**
|
|
188
|
+
* returns a wrapper for the setState function that will update the state and all the subscribers
|
|
189
|
+
* @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
|
|
190
|
+
* @returns {StateSetter<TState>} - The state setter
|
|
191
|
+
* */
|
|
192
|
+
this.getSetStateWrapper = ({ invokerSetState, } = {}) => {
|
|
193
|
+
const setState = (setter) => {
|
|
194
|
+
this.computeSetState({ invokerSetState, setter });
|
|
74
195
|
};
|
|
196
|
+
return setState;
|
|
75
197
|
};
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
this.
|
|
83
|
-
|
|
198
|
+
/**
|
|
199
|
+
* Calculate whenever or not we should compute the callback parameters on the state change
|
|
200
|
+
* @returns {boolean} - True if we should compute the callback parameters on the state change
|
|
201
|
+
* */
|
|
202
|
+
this.hasStateCallbacks = () => {
|
|
203
|
+
const { computePreventStateChange, onStateChanged } = this;
|
|
204
|
+
const { computePreventStateChange: computePreventStateChangeFromConfig, onStateChanged: onStateChangedFromConfig, } = this.config;
|
|
205
|
+
const preventStateChangesCalls = computePreventStateChange || computePreventStateChangeFromConfig;
|
|
206
|
+
const stateChangeCalls = onStateChanged || onStateChangedFromConfig;
|
|
207
|
+
const shouldComputeParameter = preventStateChangesCalls || stateChangeCalls;
|
|
208
|
+
return !!shouldComputeParameter;
|
|
209
|
+
};
|
|
210
|
+
/**
|
|
211
|
+
* This is responsible for defining whenever or not the state change should be allowed or prevented
|
|
212
|
+
* the function also execute the functions:
|
|
213
|
+
* - onStateChanged (if defined) - this function is executed after the state change
|
|
214
|
+
* - 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
|
|
215
|
+
* @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
|
|
216
|
+
*/
|
|
217
|
+
this.computeSetState = ({ setter, invokerSetState, }) => {
|
|
218
|
+
const isSetterFunction = typeof setter === 'function';
|
|
219
|
+
const previousState = this.getStateClone();
|
|
220
|
+
const newState = isSetterFunction
|
|
221
|
+
? setter(previousState)
|
|
222
|
+
: setter;
|
|
223
|
+
const itHasStateCallbacks = this.hasStateCallbacks();
|
|
224
|
+
const actions = itHasStateCallbacks && this.getStoreActionsMap({});
|
|
225
|
+
const setState = itHasStateCallbacks && this.getSetStateWrapper({ invokerSetState });
|
|
226
|
+
const { setMetadata, getMetadataClone: getMetadata, getStateClone: getState, } = this;
|
|
227
|
+
const callbackParameter = {
|
|
228
|
+
setMetadata,
|
|
229
|
+
getMetadata,
|
|
230
|
+
setState,
|
|
231
|
+
getState,
|
|
232
|
+
actions,
|
|
233
|
+
previousState,
|
|
234
|
+
state: newState,
|
|
235
|
+
};
|
|
236
|
+
const { computePreventStateChange } = this;
|
|
237
|
+
const { computePreventStateChange: computePreventStateChangeFromConfig } = this.config;
|
|
238
|
+
// check if the state change should be prevented
|
|
239
|
+
if (computePreventStateChange || computePreventStateChangeFromConfig) {
|
|
240
|
+
const preventStateChange = (computePreventStateChange === null || computePreventStateChange === void 0 ? void 0 : computePreventStateChange(callbackParameter)) ||
|
|
241
|
+
(computePreventStateChangeFromConfig === null || computePreventStateChangeFromConfig === void 0 ? void 0 : computePreventStateChangeFromConfig(callbackParameter));
|
|
242
|
+
if (preventStateChange)
|
|
84
243
|
return;
|
|
85
|
-
|
|
244
|
+
}
|
|
245
|
+
this.setState({
|
|
246
|
+
invokerSetState,
|
|
247
|
+
state: newState,
|
|
86
248
|
});
|
|
249
|
+
const { onStateChanged } = this;
|
|
250
|
+
const { onStateChanged: onStateChangedFromConfig } = this.config;
|
|
251
|
+
if (!onStateChanged && !onStateChangedFromConfig)
|
|
252
|
+
return;
|
|
253
|
+
onStateChanged === null || onStateChanged === void 0 ? void 0 : onStateChanged(callbackParameter);
|
|
254
|
+
onStateChangedFromConfig === null || onStateChangedFromConfig === void 0 ? void 0 : onStateChangedFromConfig(callbackParameter);
|
|
87
255
|
};
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
this.
|
|
94
|
-
|
|
256
|
+
/**
|
|
257
|
+
* This creates a map of actions that can be used to modify or interact with the state
|
|
258
|
+
* @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
|
|
259
|
+
* @returns {ActionCollectionResult<TState, TMetadata, TStateSetter>} - The actions map result of the configuration object passed to the constructor
|
|
260
|
+
* */
|
|
261
|
+
this.getStoreActionsMap = ({ invokerSetState, }) => {
|
|
262
|
+
if (!this.setterConfig)
|
|
263
|
+
return null;
|
|
264
|
+
const { setterConfig, setMetadata } = this;
|
|
265
|
+
const actionsConfig = setterConfig;
|
|
95
266
|
const actionsKeys = Object.keys(actionsConfig);
|
|
96
|
-
const
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
267
|
+
const setState = this.getSetStateWrapper({
|
|
268
|
+
invokerSetState,
|
|
269
|
+
});
|
|
270
|
+
// we expose a copy of the state and metadata to the actions to prevent them from modifying the state directly
|
|
271
|
+
const { getStateClone: getState, getMetadataClone: getMetadata } = this;
|
|
272
|
+
// we bind the functions to the actions object to allow reusing actions in the same api config by using the -this- keyword
|
|
273
|
+
const actions = actionsKeys.reduce((accumulator, action_key) => (Object.assign(Object.assign({}, accumulator), { [action_key](...parameres) {
|
|
274
|
+
const actionConfig = actionsConfig[action_key];
|
|
275
|
+
const action = actionConfig.apply(actions, parameres);
|
|
276
|
+
const actionIsNotAFunction = typeof action !== 'function';
|
|
277
|
+
// we throw an error if the action is not a function, this is mandatory for the correct execution of the actions
|
|
278
|
+
if (actionIsNotAFunction) {
|
|
279
|
+
throwWrongKeyOnActionCollectionConfig(action_key);
|
|
280
|
+
}
|
|
100
281
|
// executes the actions bringing access to the state setter and a copy of the state
|
|
101
|
-
const result = action(
|
|
282
|
+
const result = action.call(actions, {
|
|
283
|
+
setState,
|
|
284
|
+
getState,
|
|
285
|
+
setMetadata,
|
|
286
|
+
getMetadata,
|
|
287
|
+
});
|
|
288
|
+
// we return the result of the actions to the invoker
|
|
102
289
|
return result;
|
|
103
290
|
} })), {});
|
|
104
|
-
return
|
|
291
|
+
return actions;
|
|
105
292
|
};
|
|
106
|
-
this.
|
|
107
|
-
if (!this.isPersistStore)
|
|
108
|
-
return;
|
|
109
|
-
yield async_storage_1.default.removeItem(this.persistStoreAs);
|
|
110
|
-
});
|
|
111
|
-
}
|
|
112
|
-
get isStoredStateItemUpdated() {
|
|
113
|
-
return this.storedStateItem !== undefined;
|
|
114
|
-
}
|
|
115
|
-
asyncStorageGetItem() {
|
|
116
|
-
return async_storage_1.default.getItem(this.persistStoreAs);
|
|
117
|
-
}
|
|
118
|
-
getAsyncStoreItem({ invokerSetState }) {
|
|
119
|
-
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
120
|
-
// If the state is already updated, return it
|
|
121
|
-
if (this.isStoredStateItemUpdated)
|
|
122
|
-
return this.storedStateItem;
|
|
123
|
-
// If the promise to get the state is already running, return it
|
|
124
|
-
if (this.getAsyncStoreItemPromise)
|
|
125
|
-
return this.getAsyncStoreItemPromise;
|
|
126
|
-
this.getAsyncStoreItemPromise = new Promise((resolve) => {
|
|
127
|
-
(() => tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
128
|
-
var _a;
|
|
129
|
-
const item = yield this.asyncStorageGetItem();
|
|
130
|
-
if (item) {
|
|
131
|
-
let value = JSON.parse(item);
|
|
132
|
-
/** This allow users to review what is been stored */
|
|
133
|
-
value = (_a = this.onPersistStorageLoad(value)) !== null && _a !== void 0 ? _a : value;
|
|
134
|
-
const newState = (0, json_storage_formatter_1.formatFromStore)(value);
|
|
135
|
-
const stateSetter = this.getInternalSetter({ invokerSetState });
|
|
136
|
-
stateSetter(newState);
|
|
137
|
-
}
|
|
138
|
-
resolve(this.state);
|
|
139
|
-
}))();
|
|
140
|
-
});
|
|
141
|
-
return this.getAsyncStoreItemPromise;
|
|
142
|
-
});
|
|
143
|
-
}
|
|
144
|
-
asyncStorageSetItem(valueToStore) {
|
|
145
|
-
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
146
|
-
yield async_storage_1.default.setItem(this.persistStoreAs, valueToStore);
|
|
147
|
-
});
|
|
148
|
-
}
|
|
149
|
-
setAsyncStoreItem() {
|
|
150
|
-
return tslib_1.__awaiter(this, void 0, void 0, function* () {
|
|
151
|
-
if (this.storedStateItem === this.state)
|
|
152
|
-
return;
|
|
153
|
-
this.storedStateItem = this.state;
|
|
154
|
-
const valueToStore = (0, json_storage_formatter_1.formatToStore)(this.state);
|
|
155
|
-
yield this.asyncStorageSetItem(JSON.stringify(valueToStore));
|
|
156
|
-
});
|
|
293
|
+
this.onInitializeStore();
|
|
157
294
|
}
|
|
295
|
+
/**
|
|
296
|
+
* Returns the state setter or the actions map
|
|
297
|
+
* @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
|
|
298
|
+
* @returns {TStateSetter} - The state setter or the actions map
|
|
299
|
+
* */
|
|
158
300
|
getStateOrchestrator(invokerSetState) {
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
});
|
|
301
|
+
const stateHasCustomActions = this.setterConfig;
|
|
302
|
+
if (stateHasCustomActions) {
|
|
303
|
+
return this.getStoreActionsMap({ invokerSetState });
|
|
163
304
|
}
|
|
164
|
-
return this.
|
|
305
|
+
return this.getSetStateWrapper({ invokerSetState });
|
|
165
306
|
}
|
|
166
307
|
}
|
|
167
308
|
exports.GlobalStore = GlobalStore;
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @param {StateSetter<TState>} setter - add a new state to an existing state
|
|
3
|
+
* @returns {void} result - void
|
|
4
|
+
*/
|
|
5
|
+
export type StateSetter<TState> = (setter: TState | ((state: TState) => TState)) => void;
|
|
6
|
+
/**
|
|
7
|
+
* Parameters of the onStateChanged callback function
|
|
8
|
+
* @param {TState} state - the new state
|
|
9
|
+
* @param {TState} previousState - the previous state
|
|
10
|
+
**/
|
|
11
|
+
export type StateChanges<TState> = {
|
|
12
|
+
state: TState;
|
|
13
|
+
previousState?: TState;
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* Callbacks to be passed to the configurating function of the store
|
|
17
|
+
* @template {TState} TState - The state type
|
|
18
|
+
* @template {TMetadata} TMetadata - The metadata type
|
|
19
|
+
* @property {StateSetter<TState>} setMetadata - Set the metadata
|
|
20
|
+
* @property {StateSetter<TState>} setState - Set the state
|
|
21
|
+
* @property {() => TState} getState - Get the state
|
|
22
|
+
* @property {() => TMetadata} getMetadata - Get the metadata
|
|
23
|
+
**/
|
|
24
|
+
export type StoreTools<TState, TMetadata = null> = {
|
|
25
|
+
setMetadata: StateSetter<TMetadata>;
|
|
26
|
+
setState: StateSetter<TState>;
|
|
27
|
+
getState: () => TState;
|
|
28
|
+
getMetadata: () => TMetadata;
|
|
29
|
+
};
|
|
30
|
+
/**
|
|
31
|
+
* Basic contract for the storeActionsConfig configuration
|
|
32
|
+
* @template {TState} TState - The state type
|
|
33
|
+
* @template {TMetadata} TMetadata - The metadata type
|
|
34
|
+
* @property {string} key - The action name
|
|
35
|
+
* @property {(...parameters: unknown[]) => (storeTools: { setMetadata: StateSetter<TMetadata>; setState: StateSetter<TState>; getState: () => TState; getMetadata: () => TMetadata; }) => unknown | void} value - The action function
|
|
36
|
+
* @returns {ActionCollectionConfig<TState, TMetadata>} result - The action collection configuration
|
|
37
|
+
*/
|
|
38
|
+
export interface ActionCollectionConfig<TState, TMetadata> {
|
|
39
|
+
[key: string]: (...parameters: any[]) => (storeTools: StoreTools<TState, TMetadata>) => unknown | void;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* This is the actions object returned by the hook when you pass an storeActionsConfig configuration
|
|
43
|
+
* if you pass an storeActionsConfig configuration, the hook will return an object with the actions
|
|
44
|
+
* whatever data manipulation of the state should be executed through the custom actions with as access to the state and metadata
|
|
45
|
+
* @template {TState} TState - The state type
|
|
46
|
+
* @template {TMetadata} TMetadata - The metadata type
|
|
47
|
+
* @template {TStateSetter} TStateSetter - The storeActionsConfig type (optional) - if you pass an storeActionsConfig the hook will return an object with the actions
|
|
48
|
+
*
|
|
49
|
+
* @example
|
|
50
|
+
*
|
|
51
|
+
* const store = new GlobalStore(0, {
|
|
52
|
+
* increment: () => ({ setState }) => {
|
|
53
|
+
* setState((state) => state + 1);
|
|
54
|
+
* },
|
|
55
|
+
* decrement: () => ({ setState }) => {
|
|
56
|
+
* setState((state) => state - 1);
|
|
57
|
+
* },
|
|
58
|
+
* });
|
|
59
|
+
*
|
|
60
|
+
* const [state, actions] = store.getHook();
|
|
61
|
+
*
|
|
62
|
+
* actions.increment();
|
|
63
|
+
* actions.decrement();
|
|
64
|
+
*
|
|
65
|
+
* console.log(state); // 0
|
|
66
|
+
*/
|
|
67
|
+
export type ActionCollectionResult<TState, TMetadata, TStateSetter extends ActionCollectionConfig<TState, TMetadata> | StateSetter<TState> = StateSetter<TState>> = TStateSetter extends ActionCollectionConfig<TState, TMetadata> ? {
|
|
68
|
+
[key in keyof TStateSetter]: (...params: Parameters<TStateSetter[key]>) => ReturnType<ReturnType<TStateSetter[key]>>;
|
|
69
|
+
} : null;
|
|
70
|
+
/**
|
|
71
|
+
* Common parameters of the store configuration callback functions
|
|
72
|
+
* @param {StateSetter<TState>} setState - add a new value to the state
|
|
73
|
+
* @param {() => TState} getState - get the current state
|
|
74
|
+
* @param {StateSetter<TMetadata>} setMetadata - add a new value to the metadata
|
|
75
|
+
* @param {() => TMetadata} getMetadata - get the current metadata
|
|
76
|
+
* @param {ActionCollectionResult<TState, ActionCollectionConfig<TState, TMetadata>> | null} actions - the actions object returned by the hook when you pass an storeActionsConfig configuration otherwise null
|
|
77
|
+
* @template {TState} TState - The state type
|
|
78
|
+
* @template {TMetadata} TMetadata - The metadata type
|
|
79
|
+
* @template {TStateSetter} TStateSetter - The storeActionsConfig type (optional) - if you pass an storeActionsConfig the hook will return an object with the actions
|
|
80
|
+
* @template {ActionCollectionResult<TState, TStateSetter>} TStateSetter - the result of the API (optional) - if you don't pass an API as a parameter, you can pass null
|
|
81
|
+
* */
|
|
82
|
+
export type StateConfigCallbackParam<TState, TMetadata, TStateSetter extends ActionCollectionConfig<TState, TMetadata> | StateSetter<TState> = StateSetter<TState>> = {
|
|
83
|
+
actions: TStateSetter extends ActionCollectionConfig<TState, TMetadata> ? ActionCollectionResult<TState, TMetadata, TStateSetter> : null;
|
|
84
|
+
} & StoreTools<TState, TMetadata>;
|
|
85
|
+
/**
|
|
86
|
+
* Parameters of the onStateChanged callback function
|
|
87
|
+
* @template {TState} TState - The state type
|
|
88
|
+
* @template {TMetadata} TMetadata - The metadata type
|
|
89
|
+
* @template {TStateSetter} TStateSetter - The storeActionsConfig type (optional) - if you pass an storeActionsConfig the hook will return an object with the actions
|
|
90
|
+
*/
|
|
91
|
+
export type StateChangesParam<TState, TMetadata, TStateSetter extends ActionCollectionConfig<TState, TMetadata> | StateSetter<TState> = StateSetter<TState>> = StateConfigCallbackParam<TState, TMetadata, TStateSetter> & StateChanges<TState>;
|
|
92
|
+
/**
|
|
93
|
+
* Configuration of the store (optional) - if you don't need to use the store configuration you don't need to pass this parameter
|
|
94
|
+
* @param {StateConfigCallbackParam<TState, TMetadata> => void} onInit - callback function called when the store is initialized
|
|
95
|
+
* @param {StateConfigCallbackParam<TState, TMetadata> => void} onSubscribed - callback function called every time a component is subscribed to the store
|
|
96
|
+
* @param {StateChangesParam<TState, TMetadata> => boolean} computePreventStateChange - callback function called every time the state is changed and it allows you to prevent the state change
|
|
97
|
+
* @param {StateChangesParam<TState, TMetadata> => void} onStateChanged - callback function called every time the state is changed
|
|
98
|
+
* @template TState - the type of the state
|
|
99
|
+
* @template TMetadata - the type of the metadata (optional) - if you don't pass an metadata as a parameter, you can pass null
|
|
100
|
+
* @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
|
|
101
|
+
* */
|
|
102
|
+
export type GlobalStoreConfig<TState, TMetadata, TStateSetter extends ActionCollectionConfig<TState, TMetadata> | StateSetter<TState> = StateSetter<TState>> = {
|
|
103
|
+
onInit?: (parameters: StateConfigCallbackParam<TState, TMetadata, TStateSetter>) => void;
|
|
104
|
+
onStateChanged?: (parameters: StateChangesParam<TState, TMetadata, TStateSetter>) => void;
|
|
105
|
+
onSubscribed?: (parameters: StateConfigCallbackParam<TState, TMetadata, TStateSetter>) => void;
|
|
106
|
+
computePreventStateChange?: (parameters: StateChangesParam<TState, TMetadata, TStateSetter>) => boolean;
|
|
107
|
+
};
|
|
108
|
+
//# 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":"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"}
|
|
File without changes
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GlobalStore.utils.d.ts","sourceRoot":"","sources":["../src/GlobalStore.utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,wBAAwB,CAAC;AAG/C,OAAO,EAAE,KAAK,EAAE,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.clone = void 0;
|
|
4
|
+
const json_storage_formatter_1 = require("json-storage-formatter");
|
|
5
|
+
Object.defineProperty(exports, "clone", { enumerable: true, get: function () { return json_storage_formatter_1.clone; } });
|
package/lib/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC;AACpC,cAAc,eAAe,CAAC"}
|
package/lib/index.js
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const tslib_1 = require("tslib");
|
|
4
|
+
tslib_1.__exportStar(require("./GlobalStore.types"), exports);
|
|
5
|
+
tslib_1.__exportStar(require("./GlobalStore.utils"), exports);
|
|
6
|
+
tslib_1.__exportStar(require("./GlobalStore"), exports);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native-global-state-hooks",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.1.1",
|
|
4
4
|
"description": "This is a package to easily handling global-state across your react-native-components No-redux",
|
|
5
5
|
"main": "lib/GlobalStore.js",
|
|
6
6
|
"files": [
|
|
@@ -40,7 +40,6 @@
|
|
|
40
40
|
},
|
|
41
41
|
"homepage": "https://github.com/johnny-quesada-developer/react-native-global-state-hooks#readme",
|
|
42
42
|
"devDependencies": {
|
|
43
|
-
"@react-native-async-storage/async-storage": "workspace:*",
|
|
44
43
|
"@types/jest": "^26.0.17",
|
|
45
44
|
"@types/lodash": "^4.14.165",
|
|
46
45
|
"@types/react": "^17.0.0",
|
|
@@ -48,6 +47,7 @@
|
|
|
48
47
|
"@types/react-test-renderer": "^17.0.0",
|
|
49
48
|
"@typescript-eslint/eslint-plugin": "^4.9.1",
|
|
50
49
|
"@typescript-eslint/parser": "^4.9.1",
|
|
50
|
+
"cancelable-promise-jq": "^1.0.4",
|
|
51
51
|
"eslint": "^7.15.0",
|
|
52
52
|
"eslint-config-airbnb": "^18.2.1",
|
|
53
53
|
"eslint-plugin-import": "^2.22.1",
|
|
@@ -59,13 +59,12 @@
|
|
|
59
59
|
"react-test-renderer": "^17.0.1",
|
|
60
60
|
"ts-jest": "^26.4.4",
|
|
61
61
|
"tslib": "^2.5.0",
|
|
62
|
-
"typescript": "^4.
|
|
62
|
+
"typescript": "^4.9.5"
|
|
63
63
|
},
|
|
64
64
|
"peerDependencies": {
|
|
65
|
-
"@react-native-async-storage/async-storage": "workspace:*",
|
|
66
65
|
"react": "workspace:*"
|
|
67
66
|
},
|
|
68
67
|
"dependencies": {
|
|
69
|
-
"json-storage-formatter": "^1.0.
|
|
68
|
+
"json-storage-formatter": "^1.0.3"
|
|
70
69
|
}
|
|
71
70
|
}
|