@dr.pogodin/react-global-state 0.17.4 → 0.18.0
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/build/common/GlobalStateProvider.js +4 -4
- package/build/common/GlobalStateProvider.js.map +1 -1
- package/build/common/useAsyncCollection.js +1 -1
- package/build/common/useAsyncCollection.js.map +1 -1
- package/build/common/useAsyncData.js +45 -35
- package/build/common/useAsyncData.js.map +1 -1
- package/build/common/useGlobalState.js +1 -1
- package/build/common/useGlobalState.js.map +1 -1
- package/build/module/GlobalStateProvider.js +5 -5
- package/build/module/GlobalStateProvider.js.map +1 -1
- package/build/module/useAsyncCollection.js +1 -1
- package/build/module/useAsyncCollection.js.map +1 -1
- package/build/module/useAsyncData.js +45 -35
- package/build/module/useAsyncData.js.map +1 -1
- package/build/module/useGlobalState.js +1 -1
- package/build/module/useGlobalState.js.map +1 -1
- package/build/types/useAsyncData.d.ts +1 -0
- package/build/types/useGlobalState.d.ts +2 -1
- package/package.json +29 -30
- package/src/GlobalStateProvider.tsx +5 -9
- package/src/useAsyncCollection.ts +1 -1
- package/src/useAsyncData.ts +59 -50
- package/src/useGlobalState.ts +10 -3
package/src/useAsyncData.ts
CHANGED
|
@@ -57,6 +57,7 @@ export function newAsyncDataEnvelope<DataT>(
|
|
|
57
57
|
|
|
58
58
|
export type UseAsyncDataOptionsT = {
|
|
59
59
|
deps?: unknown[];
|
|
60
|
+
disabled?: boolean;
|
|
60
61
|
garbageCollectAge?: number;
|
|
61
62
|
maxage?: number;
|
|
62
63
|
noSSR?: boolean;
|
|
@@ -242,8 +243,8 @@ function useAsyncData<DataT>(
|
|
|
242
243
|
};
|
|
243
244
|
}
|
|
244
245
|
|
|
245
|
-
if (globalState.ssrContext
|
|
246
|
-
if (!state.
|
|
246
|
+
if (globalState.ssrContext) {
|
|
247
|
+
if (!options.disabled && !options.noSSR && !state.operationId && !state.timestamp) {
|
|
247
248
|
globalState.ssrContext.pending.push(
|
|
248
249
|
load(path, loader, globalState, {
|
|
249
250
|
data: state.data,
|
|
@@ -252,6 +253,8 @@ function useAsyncData<DataT>(
|
|
|
252
253
|
);
|
|
253
254
|
}
|
|
254
255
|
} else {
|
|
256
|
+
const { disabled } = options;
|
|
257
|
+
|
|
255
258
|
// This takes care about the client-side reference counting, and garbage
|
|
256
259
|
// collection.
|
|
257
260
|
//
|
|
@@ -263,62 +266,68 @@ function useAsyncData<DataT>(
|
|
|
263
266
|
// The same applies to other useEffect() hooks below.
|
|
264
267
|
useEffect(() => { // eslint-disable-line react-hooks/rules-of-hooks
|
|
265
268
|
const numRefsPath = path ? `${path}.numRefs` : 'numRefs';
|
|
266
|
-
|
|
267
|
-
|
|
269
|
+
if (!disabled) {
|
|
270
|
+
const numRefs = globalState.get<ForceT, number>(numRefsPath);
|
|
271
|
+
globalState.set<ForceT, number>(numRefsPath, numRefs + 1);
|
|
272
|
+
}
|
|
268
273
|
return () => {
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
path
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
274
|
+
if (!disabled) {
|
|
275
|
+
const state2: AsyncDataEnvelopeT<DataT> = globalState.get<
|
|
276
|
+
ForceT, AsyncDataEnvelopeT<DataT>>(
|
|
277
|
+
path,
|
|
278
|
+
);
|
|
279
|
+
if (
|
|
280
|
+
state2.numRefs === 1
|
|
281
|
+
&& garbageCollectAge < Date.now() - state2.timestamp
|
|
282
|
+
) {
|
|
283
|
+
if (process.env.NODE_ENV !== 'production' && isDebugMode()) {
|
|
284
|
+
/* eslint-disable no-console */
|
|
285
|
+
console.log(
|
|
286
|
+
`ReactGlobalState - useAsyncData garbage collected at path ${
|
|
287
|
+
path || ''
|
|
288
|
+
}`,
|
|
289
|
+
);
|
|
290
|
+
/* eslint-enable no-console */
|
|
291
|
+
}
|
|
292
|
+
globalState.dropDependencies(path || '');
|
|
293
|
+
globalState.set<ForceT, AsyncDataEnvelopeT<DataT>>(path, {
|
|
294
|
+
...state2,
|
|
295
|
+
data: null,
|
|
296
|
+
numRefs: 0,
|
|
297
|
+
timestamp: 0,
|
|
298
|
+
});
|
|
299
|
+
} else globalState.set<ForceT, number>(numRefsPath, state2.numRefs - 1);
|
|
300
|
+
}
|
|
294
301
|
};
|
|
295
|
-
}, [garbageCollectAge, globalState, path]);
|
|
302
|
+
}, [disabled, garbageCollectAge, globalState, path]);
|
|
296
303
|
|
|
297
304
|
// Note: a bunch of Rules of Hooks ignored belows because in our very
|
|
298
305
|
// special case the otherwise wrong behavior is actually what we need.
|
|
299
306
|
|
|
300
307
|
// Data loading and refreshing.
|
|
301
308
|
useEffect(() => { // eslint-disable-line react-hooks/rules-of-hooks
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
309
|
+
if (!disabled) {
|
|
310
|
+
const state2: AsyncDataEnvelopeT<DataT> = globalState.get<
|
|
311
|
+
ForceT, AsyncDataEnvelopeT<DataT>>(path);
|
|
312
|
+
|
|
313
|
+
const { deps } = options;
|
|
314
|
+
if (
|
|
315
|
+
// The hook is called with a list of dependencies, that mismatch
|
|
316
|
+
// dependencies last used to retrieve the data at given path.
|
|
317
|
+
(deps && globalState.hasChangedDependencies(path || '', deps))
|
|
318
|
+
|
|
319
|
+
// Data at the path are stale, and are not being loaded.
|
|
320
|
+
|| (
|
|
321
|
+
refreshAge < Date.now() - state2.timestamp
|
|
322
|
+
&& (!state2.operationId || state2.operationId.charAt(0) === 'S')
|
|
323
|
+
)
|
|
324
|
+
) {
|
|
325
|
+
if (!deps) globalState.dropDependencies(path || '');
|
|
326
|
+
load(path, loader, globalState, {
|
|
327
|
+
data: state2.data,
|
|
328
|
+
timestamp: state2.timestamp,
|
|
329
|
+
});
|
|
330
|
+
}
|
|
322
331
|
}
|
|
323
332
|
});
|
|
324
333
|
}
|
package/src/useGlobalState.ts
CHANGED
|
@@ -1,7 +1,14 @@
|
|
|
1
1
|
// Hook for updates of global state.
|
|
2
2
|
|
|
3
3
|
import { isFunction } from 'lodash';
|
|
4
|
-
|
|
4
|
+
|
|
5
|
+
import {
|
|
6
|
+
type Dispatch,
|
|
7
|
+
type SetStateAction,
|
|
8
|
+
useEffect,
|
|
9
|
+
useRef,
|
|
10
|
+
useSyncExternalStore,
|
|
11
|
+
} from 'react';
|
|
5
12
|
|
|
6
13
|
import { Emitter } from '@dr.pogodin/js-utils';
|
|
7
14
|
|
|
@@ -19,7 +26,7 @@ import {
|
|
|
19
26
|
isDebugMode,
|
|
20
27
|
} from './utils';
|
|
21
28
|
|
|
22
|
-
export type SetterT<T> =
|
|
29
|
+
export type SetterT<T> = Dispatch<SetStateAction<T>>;
|
|
23
30
|
|
|
24
31
|
type ListenerT = () => void;
|
|
25
32
|
|
|
@@ -121,7 +128,7 @@ function useGlobalState(
|
|
|
121
128
|
): UseGlobalStateResT<any> {
|
|
122
129
|
const globalState = getGlobalState();
|
|
123
130
|
|
|
124
|
-
const ref = useRef<GlobalStateRef>();
|
|
131
|
+
const ref = useRef<GlobalStateRef>(undefined);
|
|
125
132
|
|
|
126
133
|
let rc: GlobalStateRef;
|
|
127
134
|
if (!ref.current) {
|