@t8/react-pending 1.0.27 → 1.0.29
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/dist/index.cjs +118 -0
- package/dist/index.d.ts +23 -18
- package/dist/index.mjs +116 -0
- package/package.json +8 -9
- package/src/usePendingState.ts +6 -5
- package/dist/index.js +0 -169
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
let react = require("react");
|
|
2
|
+
let __t8_react_store = require("@t8/react-store");
|
|
3
|
+
let react_jsx_runtime = require("react/jsx-runtime");
|
|
4
|
+
|
|
5
|
+
//#region src/PendingStateContext.ts
|
|
6
|
+
const PendingStateContext = (0, react.createContext)(/* @__PURE__ */ new Map());
|
|
7
|
+
|
|
8
|
+
//#endregion
|
|
9
|
+
//#region src/PendingStateProvider.tsx
|
|
10
|
+
const PendingStateProvider = ({ value, children }) => {
|
|
11
|
+
let defaultValueRef = (0, react.useRef)(null);
|
|
12
|
+
let resolvedValue = (0, react.useMemo)(() => {
|
|
13
|
+
if (value instanceof Map) return value;
|
|
14
|
+
if (typeof value === "object" && value !== null) return new Map(Object.entries(value).map(([key, state]) => [key, new __t8_react_store.Store(state)]));
|
|
15
|
+
if (defaultValueRef.current === null) defaultValueRef.current = /* @__PURE__ */ new Map();
|
|
16
|
+
return defaultValueRef.current;
|
|
17
|
+
}, [value]);
|
|
18
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(PendingStateContext.Provider, {
|
|
19
|
+
value: resolvedValue,
|
|
20
|
+
children
|
|
21
|
+
});
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
//#endregion
|
|
25
|
+
//#region src/usePendingState.ts
|
|
26
|
+
function createState(initialized = false, complete = false, error) {
|
|
27
|
+
return {
|
|
28
|
+
initialized,
|
|
29
|
+
complete,
|
|
30
|
+
error,
|
|
31
|
+
time: Date.now()
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Returns an instance of an action's state and the functions to update it.
|
|
36
|
+
*
|
|
37
|
+
* @param store - A unique store key or a store. Providing a store
|
|
38
|
+
* key or a shared store allows to share the state across multiple
|
|
39
|
+
* components.
|
|
40
|
+
*
|
|
41
|
+
* @returns `[state, withState, setState]`, where
|
|
42
|
+
* - `state` is the current value of the action's state;
|
|
43
|
+
* - `withState(action, options?)` reads and tracks the `actions`'s state
|
|
44
|
+
* which is exposed as `state` listed above;
|
|
45
|
+
* - `setState(update)` can replace the current `state` value directly with
|
|
46
|
+
* an another state value.
|
|
47
|
+
*/
|
|
48
|
+
function usePendingState(store) {
|
|
49
|
+
let storeMap = (0, react.useContext)(PendingStateContext);
|
|
50
|
+
let storeRef = (0, react.useRef)(null);
|
|
51
|
+
let [storeItemInited, setStoreItemInited] = (0, react.useState)(false);
|
|
52
|
+
let [state, setState] = (0, __t8_react_store.useStore)((0, react.useMemo)(() => {
|
|
53
|
+
if ((0, __t8_react_store.isStore)(store)) return store;
|
|
54
|
+
if (typeof store === "string") {
|
|
55
|
+
let storeItem = storeMap.get(store);
|
|
56
|
+
if (!storeItem) {
|
|
57
|
+
storeItem = new __t8_react_store.Store(createState());
|
|
58
|
+
storeMap.set(store, storeItem);
|
|
59
|
+
if (!storeItemInited) setStoreItemInited(true);
|
|
60
|
+
}
|
|
61
|
+
return storeItem;
|
|
62
|
+
}
|
|
63
|
+
if (!storeRef.current) storeRef.current = new __t8_react_store.Store(createState());
|
|
64
|
+
return storeRef.current;
|
|
65
|
+
}, [
|
|
66
|
+
store,
|
|
67
|
+
storeMap,
|
|
68
|
+
storeItemInited
|
|
69
|
+
]));
|
|
70
|
+
return [
|
|
71
|
+
state,
|
|
72
|
+
(0, react.useCallback)((value, options) => {
|
|
73
|
+
if (value instanceof Promise) {
|
|
74
|
+
let delayedPending = null;
|
|
75
|
+
if (!options?.silent) {
|
|
76
|
+
let delay = options?.delay;
|
|
77
|
+
if (delay === void 0) setState((prevState) => ({
|
|
78
|
+
...prevState,
|
|
79
|
+
...createState(true, false)
|
|
80
|
+
}));
|
|
81
|
+
else delayedPending = setTimeout(() => {
|
|
82
|
+
setState((prevState) => ({
|
|
83
|
+
...prevState,
|
|
84
|
+
...createState(true, false)
|
|
85
|
+
}));
|
|
86
|
+
delayedPending = null;
|
|
87
|
+
}, delay);
|
|
88
|
+
}
|
|
89
|
+
return value.then((resolvedValue) => {
|
|
90
|
+
if (delayedPending !== null) clearTimeout(delayedPending);
|
|
91
|
+
setState((prevState) => ({
|
|
92
|
+
...prevState,
|
|
93
|
+
...createState(true, true)
|
|
94
|
+
}));
|
|
95
|
+
return resolvedValue;
|
|
96
|
+
}).catch((error) => {
|
|
97
|
+
if (delayedPending !== null) clearTimeout(delayedPending);
|
|
98
|
+
setState((prevState) => ({
|
|
99
|
+
...prevState,
|
|
100
|
+
...createState(true, true, error)
|
|
101
|
+
}));
|
|
102
|
+
if (options?.throws) throw error;
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
setState((prevState) => ({
|
|
106
|
+
...prevState,
|
|
107
|
+
...createState(true, true)
|
|
108
|
+
}));
|
|
109
|
+
return value;
|
|
110
|
+
}, [setState]),
|
|
111
|
+
setState
|
|
112
|
+
];
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
//#endregion
|
|
116
|
+
exports.PendingStateContext = PendingStateContext;
|
|
117
|
+
exports.PendingStateProvider = PendingStateProvider;
|
|
118
|
+
exports.usePendingState = usePendingState;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,19 +1,27 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
1
|
+
import * as react0 from "react";
|
|
2
|
+
import { ReactNode } from "react";
|
|
3
|
+
import { SetStoreState, Store } from "@t8/react-store";
|
|
4
|
+
import * as react_jsx_runtime0 from "react/jsx-runtime";
|
|
3
5
|
|
|
4
|
-
|
|
6
|
+
type PendingState = {
|
|
5
7
|
initialized?: boolean | undefined;
|
|
6
8
|
complete?: boolean | undefined;
|
|
7
9
|
time?: number | undefined;
|
|
8
10
|
error?: unknown;
|
|
9
11
|
};
|
|
10
|
-
|
|
11
|
-
|
|
12
|
+
|
|
13
|
+
declare const PendingStateContext: react0.Context<Map<string, Store<PendingState>>>;
|
|
14
|
+
|
|
15
|
+
type PendingStateProviderProps = {
|
|
12
16
|
value?: Record<string, PendingState> | Map<string, Store<PendingState>> | null | undefined;
|
|
13
17
|
children?: ReactNode;
|
|
14
18
|
};
|
|
15
|
-
|
|
16
|
-
|
|
19
|
+
declare const PendingStateProvider: ({
|
|
20
|
+
value,
|
|
21
|
+
children
|
|
22
|
+
}: PendingStateProviderProps) => react_jsx_runtime0.JSX.Element;
|
|
23
|
+
|
|
24
|
+
type WithStateOptions = {
|
|
17
25
|
/**
|
|
18
26
|
* Whether to track the action state silently (e.g. with a background
|
|
19
27
|
* action or an optimistic update).
|
|
@@ -37,22 +45,19 @@ export type WithStateOptions = {
|
|
|
37
45
|
throws?: boolean;
|
|
38
46
|
};
|
|
39
47
|
/**
|
|
40
|
-
* Returns an instance of
|
|
48
|
+
* Returns an instance of an action's state and the functions to update it.
|
|
41
49
|
*
|
|
42
50
|
* @param store - A unique store key or a store. Providing a store
|
|
43
51
|
* key or a shared store allows to share the state across multiple
|
|
44
52
|
* components.
|
|
45
53
|
*
|
|
46
54
|
* @returns `[state, withState, setState]`, where
|
|
47
|
-
* - `state` is the current value of the
|
|
48
|
-
* - `withState(action, options?)` reads and tracks the
|
|
49
|
-
*
|
|
50
|
-
* - `setState(update)` can
|
|
55
|
+
* - `state` is the current value of the action's state;
|
|
56
|
+
* - `withState(action, options?)` reads and tracks the `actions`'s state
|
|
57
|
+
* which is exposed as `state` listed above;
|
|
58
|
+
* - `setState(update)` can replace the current `state` value directly with
|
|
59
|
+
* an another state value.
|
|
51
60
|
*/
|
|
52
|
-
|
|
53
|
-
PendingState,
|
|
54
|
-
<T>(value: T) => T,
|
|
55
|
-
SetStoreState<PendingState>
|
|
56
|
-
];
|
|
61
|
+
declare function usePendingState(store?: string | Store<PendingState> | null): [PendingState, <T>(value: T) => T, SetStoreState<PendingState>];
|
|
57
62
|
|
|
58
|
-
export {};
|
|
63
|
+
export { PendingState, PendingStateContext, PendingStateProvider, PendingStateProviderProps, WithStateOptions, usePendingState };
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { createContext, useCallback, useContext, useMemo, useRef, useState } from "react";
|
|
2
|
+
import { Store, isStore, useStore } from "@t8/react-store";
|
|
3
|
+
import { jsx } from "react/jsx-runtime";
|
|
4
|
+
|
|
5
|
+
//#region src/PendingStateContext.ts
|
|
6
|
+
const PendingStateContext = createContext(/* @__PURE__ */ new Map());
|
|
7
|
+
|
|
8
|
+
//#endregion
|
|
9
|
+
//#region src/PendingStateProvider.tsx
|
|
10
|
+
const PendingStateProvider = ({ value, children }) => {
|
|
11
|
+
let defaultValueRef = useRef(null);
|
|
12
|
+
let resolvedValue = useMemo(() => {
|
|
13
|
+
if (value instanceof Map) return value;
|
|
14
|
+
if (typeof value === "object" && value !== null) return new Map(Object.entries(value).map(([key, state]) => [key, new Store(state)]));
|
|
15
|
+
if (defaultValueRef.current === null) defaultValueRef.current = /* @__PURE__ */ new Map();
|
|
16
|
+
return defaultValueRef.current;
|
|
17
|
+
}, [value]);
|
|
18
|
+
return /* @__PURE__ */ jsx(PendingStateContext.Provider, {
|
|
19
|
+
value: resolvedValue,
|
|
20
|
+
children
|
|
21
|
+
});
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
//#endregion
|
|
25
|
+
//#region src/usePendingState.ts
|
|
26
|
+
function createState(initialized = false, complete = false, error) {
|
|
27
|
+
return {
|
|
28
|
+
initialized,
|
|
29
|
+
complete,
|
|
30
|
+
error,
|
|
31
|
+
time: Date.now()
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Returns an instance of an action's state and the functions to update it.
|
|
36
|
+
*
|
|
37
|
+
* @param store - A unique store key or a store. Providing a store
|
|
38
|
+
* key or a shared store allows to share the state across multiple
|
|
39
|
+
* components.
|
|
40
|
+
*
|
|
41
|
+
* @returns `[state, withState, setState]`, where
|
|
42
|
+
* - `state` is the current value of the action's state;
|
|
43
|
+
* - `withState(action, options?)` reads and tracks the `actions`'s state
|
|
44
|
+
* which is exposed as `state` listed above;
|
|
45
|
+
* - `setState(update)` can replace the current `state` value directly with
|
|
46
|
+
* an another state value.
|
|
47
|
+
*/
|
|
48
|
+
function usePendingState(store) {
|
|
49
|
+
let storeMap = useContext(PendingStateContext);
|
|
50
|
+
let storeRef = useRef(null);
|
|
51
|
+
let [storeItemInited, setStoreItemInited] = useState(false);
|
|
52
|
+
let [state, setState] = useStore(useMemo(() => {
|
|
53
|
+
if (isStore(store)) return store;
|
|
54
|
+
if (typeof store === "string") {
|
|
55
|
+
let storeItem = storeMap.get(store);
|
|
56
|
+
if (!storeItem) {
|
|
57
|
+
storeItem = new Store(createState());
|
|
58
|
+
storeMap.set(store, storeItem);
|
|
59
|
+
if (!storeItemInited) setStoreItemInited(true);
|
|
60
|
+
}
|
|
61
|
+
return storeItem;
|
|
62
|
+
}
|
|
63
|
+
if (!storeRef.current) storeRef.current = new Store(createState());
|
|
64
|
+
return storeRef.current;
|
|
65
|
+
}, [
|
|
66
|
+
store,
|
|
67
|
+
storeMap,
|
|
68
|
+
storeItemInited
|
|
69
|
+
]));
|
|
70
|
+
return [
|
|
71
|
+
state,
|
|
72
|
+
useCallback((value, options) => {
|
|
73
|
+
if (value instanceof Promise) {
|
|
74
|
+
let delayedPending = null;
|
|
75
|
+
if (!options?.silent) {
|
|
76
|
+
let delay = options?.delay;
|
|
77
|
+
if (delay === void 0) setState((prevState) => ({
|
|
78
|
+
...prevState,
|
|
79
|
+
...createState(true, false)
|
|
80
|
+
}));
|
|
81
|
+
else delayedPending = setTimeout(() => {
|
|
82
|
+
setState((prevState) => ({
|
|
83
|
+
...prevState,
|
|
84
|
+
...createState(true, false)
|
|
85
|
+
}));
|
|
86
|
+
delayedPending = null;
|
|
87
|
+
}, delay);
|
|
88
|
+
}
|
|
89
|
+
return value.then((resolvedValue) => {
|
|
90
|
+
if (delayedPending !== null) clearTimeout(delayedPending);
|
|
91
|
+
setState((prevState) => ({
|
|
92
|
+
...prevState,
|
|
93
|
+
...createState(true, true)
|
|
94
|
+
}));
|
|
95
|
+
return resolvedValue;
|
|
96
|
+
}).catch((error) => {
|
|
97
|
+
if (delayedPending !== null) clearTimeout(delayedPending);
|
|
98
|
+
setState((prevState) => ({
|
|
99
|
+
...prevState,
|
|
100
|
+
...createState(true, true, error)
|
|
101
|
+
}));
|
|
102
|
+
if (options?.throws) throw error;
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
setState((prevState) => ({
|
|
106
|
+
...prevState,
|
|
107
|
+
...createState(true, true)
|
|
108
|
+
}));
|
|
109
|
+
return value;
|
|
110
|
+
}, [setState]),
|
|
111
|
+
setState
|
|
112
|
+
];
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
//#endregion
|
|
116
|
+
export { PendingStateContext, PendingStateProvider, usePendingState };
|
package/package.json
CHANGED
|
@@ -1,16 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@t8/react-pending",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.29",
|
|
4
4
|
"description": "Concise async action state tracking for React apps",
|
|
5
|
-
"main": "dist/index.
|
|
6
|
-
"
|
|
5
|
+
"main": "./dist/index.cjs",
|
|
6
|
+
"module": "./dist/index.mjs",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
7
8
|
"type": "module",
|
|
8
9
|
"scripts": {
|
|
9
|
-
"clean": "node -e \"require('node:fs').rmSync('dist', { force: true, recursive: true });\"",
|
|
10
|
-
"compile": "npx esbuild index.ts --bundle --outdir=dist --platform=neutral --external:react",
|
|
11
10
|
"demo": "npx @t8/serve 3000 * tests/async_status -b src/index.tsx",
|
|
12
|
-
"preversion": "npx npm-run-all
|
|
13
|
-
"shape": "npx codeshape
|
|
11
|
+
"preversion": "npx npm-run-all shape test",
|
|
12
|
+
"shape": "npx codeshape",
|
|
14
13
|
"test": "npx playwright test --project=chromium"
|
|
15
14
|
},
|
|
16
15
|
"author": "axtk",
|
|
@@ -30,13 +29,13 @@
|
|
|
30
29
|
},
|
|
31
30
|
"devDependencies": {
|
|
32
31
|
"@playwright/test": "^1.56.0",
|
|
33
|
-
"@t8/serve": "^0.1.
|
|
32
|
+
"@t8/serve": "^0.1.37",
|
|
34
33
|
"@types/node": "^24.10.2",
|
|
35
34
|
"@types/react": "^19.2.7",
|
|
36
35
|
"@types/react-dom": "^19.2.3",
|
|
37
36
|
"react-dom": "^19.2.1"
|
|
38
37
|
},
|
|
39
38
|
"dependencies": {
|
|
40
|
-
"@t8/react-store": "^1.2.
|
|
39
|
+
"@t8/react-store": "^1.2.5"
|
|
41
40
|
}
|
|
42
41
|
}
|
package/src/usePendingState.ts
CHANGED
|
@@ -41,17 +41,18 @@ export type WithStateOptions = {
|
|
|
41
41
|
};
|
|
42
42
|
|
|
43
43
|
/**
|
|
44
|
-
* Returns an instance of
|
|
44
|
+
* Returns an instance of an action's state and the functions to update it.
|
|
45
45
|
*
|
|
46
46
|
* @param store - A unique store key or a store. Providing a store
|
|
47
47
|
* key or a shared store allows to share the state across multiple
|
|
48
48
|
* components.
|
|
49
49
|
*
|
|
50
50
|
* @returns `[state, withState, setState]`, where
|
|
51
|
-
* - `state` is the current value of the
|
|
52
|
-
* - `withState(action, options?)` reads and tracks the
|
|
53
|
-
*
|
|
54
|
-
* - `setState(update)` can
|
|
51
|
+
* - `state` is the current value of the action's state;
|
|
52
|
+
* - `withState(action, options?)` reads and tracks the `actions`'s state
|
|
53
|
+
* which is exposed as `state` listed above;
|
|
54
|
+
* - `setState(update)` can replace the current `state` value directly with
|
|
55
|
+
* an another state value.
|
|
55
56
|
*/
|
|
56
57
|
export function usePendingState(
|
|
57
58
|
store?: string | Store<PendingState> | null,
|
package/dist/index.js
DELETED
|
@@ -1,169 +0,0 @@
|
|
|
1
|
-
// src/PendingStateContext.ts
|
|
2
|
-
import { createContext } from "react";
|
|
3
|
-
var PendingStateContext = createContext(
|
|
4
|
-
/* @__PURE__ */ new Map()
|
|
5
|
-
);
|
|
6
|
-
|
|
7
|
-
// node_modules/@t8/store/src/isStore.ts
|
|
8
|
-
function isStore(x) {
|
|
9
|
-
return x !== null && typeof x === "object" && "onUpdate" in x && typeof x.onUpdate === "function" && "getState" in x && typeof x.getState === "function" && "setState" in x && typeof x.setState === "function";
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
// node_modules/@t8/store/src/isPersistentStore.ts
|
|
13
|
-
function isPersistentStore(x) {
|
|
14
|
-
return isStore(x) && "sync" in x;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
// node_modules/@t8/store/src/Store.ts
|
|
18
|
-
var Store = class {
|
|
19
|
-
state;
|
|
20
|
-
callbacks = /* @__PURE__ */ new Set();
|
|
21
|
-
revision = -1;
|
|
22
|
-
constructor(data) {
|
|
23
|
-
this.state = data;
|
|
24
|
-
}
|
|
25
|
-
onUpdate(callback) {
|
|
26
|
-
this.callbacks.add(callback);
|
|
27
|
-
return () => {
|
|
28
|
-
this.callbacks.delete(callback);
|
|
29
|
-
};
|
|
30
|
-
}
|
|
31
|
-
getState() {
|
|
32
|
-
return this.state;
|
|
33
|
-
}
|
|
34
|
-
setState(update) {
|
|
35
|
-
let prevState = this.state;
|
|
36
|
-
let nextState = update instanceof Function ? update(this.state) : update;
|
|
37
|
-
this.state = nextState;
|
|
38
|
-
this.revision = Math.random();
|
|
39
|
-
for (let callback of this.callbacks) callback(nextState, prevState);
|
|
40
|
-
}
|
|
41
|
-
};
|
|
42
|
-
|
|
43
|
-
// node_modules/@t8/react-store/src/useStore.ts
|
|
44
|
-
import { useEffect, useMemo, useRef, useState } from "react";
|
|
45
|
-
function useStore(store, shouldUpdate = true) {
|
|
46
|
-
if (!isStore(store))
|
|
47
|
-
throw new Error("'store' is not an instance of Store");
|
|
48
|
-
let [, setRevision] = useState(-1);
|
|
49
|
-
let state = store.getState();
|
|
50
|
-
let setState = useMemo(() => store.setState.bind(store), [store]);
|
|
51
|
-
let initialStoreRevision = useRef(store.revision);
|
|
52
|
-
useEffect(() => {
|
|
53
|
-
if (isPersistentStore(store)) store.syncOnce();
|
|
54
|
-
if (!shouldUpdate) return;
|
|
55
|
-
let unsubscribe = store.onUpdate((nextState, prevState) => {
|
|
56
|
-
if (typeof shouldUpdate !== "function" || shouldUpdate(nextState, prevState))
|
|
57
|
-
setRevision(Math.random());
|
|
58
|
-
});
|
|
59
|
-
if (store.revision !== initialStoreRevision.current)
|
|
60
|
-
setRevision(Math.random());
|
|
61
|
-
return () => {
|
|
62
|
-
unsubscribe();
|
|
63
|
-
initialStoreRevision.current = store.revision;
|
|
64
|
-
};
|
|
65
|
-
}, [store, shouldUpdate]);
|
|
66
|
-
return [state, setState];
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
// src/PendingStateProvider.tsx
|
|
70
|
-
import { useMemo as useMemo2, useRef as useRef2 } from "react";
|
|
71
|
-
import { jsx } from "react/jsx-runtime";
|
|
72
|
-
var PendingStateProvider = ({
|
|
73
|
-
value,
|
|
74
|
-
children
|
|
75
|
-
}) => {
|
|
76
|
-
let defaultValueRef = useRef2(null);
|
|
77
|
-
let resolvedValue = useMemo2(() => {
|
|
78
|
-
if (value instanceof Map) return value;
|
|
79
|
-
if (typeof value === "object" && value !== null)
|
|
80
|
-
return new Map(
|
|
81
|
-
Object.entries(value).map(([key, state]) => [key, new Store(state)])
|
|
82
|
-
);
|
|
83
|
-
if (defaultValueRef.current === null)
|
|
84
|
-
defaultValueRef.current = /* @__PURE__ */ new Map();
|
|
85
|
-
return defaultValueRef.current;
|
|
86
|
-
}, [value]);
|
|
87
|
-
return /* @__PURE__ */ jsx(PendingStateContext.Provider, { value: resolvedValue, children });
|
|
88
|
-
};
|
|
89
|
-
|
|
90
|
-
// src/usePendingState.ts
|
|
91
|
-
import { useCallback, useContext, useMemo as useMemo3, useRef as useRef3, useState as useState2 } from "react";
|
|
92
|
-
function createState(initialized = false, complete = false, error) {
|
|
93
|
-
return {
|
|
94
|
-
initialized,
|
|
95
|
-
complete,
|
|
96
|
-
error,
|
|
97
|
-
time: Date.now()
|
|
98
|
-
};
|
|
99
|
-
}
|
|
100
|
-
function usePendingState(store) {
|
|
101
|
-
let storeMap = useContext(PendingStateContext);
|
|
102
|
-
let storeRef = useRef3(null);
|
|
103
|
-
let [storeItemInited, setStoreItemInited] = useState2(false);
|
|
104
|
-
let resolvedStore = useMemo3(() => {
|
|
105
|
-
if (isStore(store)) return store;
|
|
106
|
-
if (typeof store === "string") {
|
|
107
|
-
let storeItem = storeMap.get(store);
|
|
108
|
-
if (!storeItem) {
|
|
109
|
-
storeItem = new Store(createState());
|
|
110
|
-
storeMap.set(store, storeItem);
|
|
111
|
-
if (!storeItemInited) setStoreItemInited(true);
|
|
112
|
-
}
|
|
113
|
-
return storeItem;
|
|
114
|
-
}
|
|
115
|
-
if (!storeRef.current) storeRef.current = new Store(createState());
|
|
116
|
-
return storeRef.current;
|
|
117
|
-
}, [store, storeMap, storeItemInited]);
|
|
118
|
-
let [state, setState] = useStore(resolvedStore);
|
|
119
|
-
let withState = useCallback(
|
|
120
|
-
(value, options) => {
|
|
121
|
-
if (value instanceof Promise) {
|
|
122
|
-
let delayedPending = null;
|
|
123
|
-
if (!options?.silent) {
|
|
124
|
-
let delay = options?.delay;
|
|
125
|
-
if (delay === void 0)
|
|
126
|
-
setState((prevState) => ({
|
|
127
|
-
...prevState,
|
|
128
|
-
...createState(true, false)
|
|
129
|
-
}));
|
|
130
|
-
else
|
|
131
|
-
delayedPending = setTimeout(() => {
|
|
132
|
-
setState((prevState) => ({
|
|
133
|
-
...prevState,
|
|
134
|
-
...createState(true, false)
|
|
135
|
-
}));
|
|
136
|
-
delayedPending = null;
|
|
137
|
-
}, delay);
|
|
138
|
-
}
|
|
139
|
-
return value.then((resolvedValue) => {
|
|
140
|
-
if (delayedPending !== null) clearTimeout(delayedPending);
|
|
141
|
-
setState((prevState) => ({
|
|
142
|
-
...prevState,
|
|
143
|
-
...createState(true, true)
|
|
144
|
-
}));
|
|
145
|
-
return resolvedValue;
|
|
146
|
-
}).catch((error) => {
|
|
147
|
-
if (delayedPending !== null) clearTimeout(delayedPending);
|
|
148
|
-
setState((prevState) => ({
|
|
149
|
-
...prevState,
|
|
150
|
-
...createState(true, true, error)
|
|
151
|
-
}));
|
|
152
|
-
if (options?.throws) throw error;
|
|
153
|
-
});
|
|
154
|
-
}
|
|
155
|
-
setState((prevState) => ({
|
|
156
|
-
...prevState,
|
|
157
|
-
...createState(true, true)
|
|
158
|
-
}));
|
|
159
|
-
return value;
|
|
160
|
-
},
|
|
161
|
-
[setState]
|
|
162
|
-
);
|
|
163
|
-
return [state, withState, setState];
|
|
164
|
-
}
|
|
165
|
-
export {
|
|
166
|
-
PendingStateContext,
|
|
167
|
-
PendingStateProvider,
|
|
168
|
-
usePendingState
|
|
169
|
-
};
|