@t8/react-pending 1.0.12 → 1.0.14
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 +31 -31
- package/dist/index.js +3 -8
- package/index.ts +4 -4
- package/package.json +46 -39
- package/src/PendingState.ts +4 -4
- package/src/PendingStateContext.ts +4 -4
- package/src/PendingStateProvider.tsx +28 -31
- package/src/usePendingState.ts +97 -99
- package/tsconfig.json +13 -13
package/README.md
CHANGED
|
@@ -13,43 +13,43 @@ Installation: `npm i @t8/react-pending`
|
|
|
13
13
|
Objective: Track the pending state of the async `fetchItems()` action to tell the user whether the UI is busy or encountered an error (preferably without rewriting the action and the app's state management).
|
|
14
14
|
|
|
15
15
|
```diff
|
|
16
|
-
+ import {usePendingState} from
|
|
16
|
+
+ import { usePendingState } from "@t8/react-pending";
|
|
17
17
|
|
|
18
18
|
const ItemList = () => {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
+
|
|
19
|
+
const [items, setItems] = useState([]);
|
|
20
|
+
// the custom string key parameter tags the action's state so
|
|
21
|
+
// that another component can access this state by the same tag
|
|
22
|
+
+ const [state, withState] = usePendingState("fetch-items");
|
|
23
23
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
-
|
|
27
|
-
+
|
|
28
|
-
|
|
24
|
+
useEffect(() => {
|
|
25
|
+
// wrapping fetchItems() to track the async action's state
|
|
26
|
+
- fetchItems().then(setItems);
|
|
27
|
+
+ withState(fetchItems()).then(setItems);
|
|
28
|
+
}, [fetchItems, withState]);
|
|
29
29
|
|
|
30
|
-
+
|
|
31
|
-
+
|
|
30
|
+
+ if (!state.complete)
|
|
31
|
+
+ return <p>Loading...</p>;
|
|
32
32
|
|
|
33
|
-
+
|
|
34
|
-
+
|
|
33
|
+
+ if (state.error)
|
|
34
|
+
+ return <p>An error occurred</p>;
|
|
35
35
|
|
|
36
|
-
|
|
36
|
+
return <ul>{items.map(/* ... */)}</ul>;
|
|
37
37
|
};
|
|
38
38
|
|
|
39
39
|
const Status = () => {
|
|
40
|
-
|
|
41
|
-
+
|
|
40
|
+
// reading the "fetch-items" state updated in ItemList
|
|
41
|
+
+ const [state] = usePendingState("fetch-items");
|
|
42
42
|
|
|
43
|
-
|
|
44
|
-
|
|
43
|
+
if (!state.initialized)
|
|
44
|
+
return "Initial";
|
|
45
45
|
|
|
46
|
-
|
|
47
|
-
|
|
46
|
+
if (!state.complete)
|
|
47
|
+
return "Busy";
|
|
48
48
|
|
|
49
|
-
|
|
50
|
-
|
|
49
|
+
if (state.error)
|
|
50
|
+
return "Error";
|
|
51
51
|
|
|
52
|
-
|
|
52
|
+
return "OK";
|
|
53
53
|
};
|
|
54
54
|
```
|
|
55
55
|
|
|
@@ -58,7 +58,7 @@ Objective: Track the pending state of the async `fetchItems()` action to tell th
|
|
|
58
58
|
🔹 If the action's state is only used within a single component, it can be used locally by omitting the custom string key parameter of the `usePendingState()` hook.
|
|
59
59
|
|
|
60
60
|
```diff
|
|
61
|
-
- const [state, withState] = usePendingState(
|
|
61
|
+
- const [state, withState] = usePendingState("fetch-items");
|
|
62
62
|
+ const [state, withState] = usePendingState();
|
|
63
63
|
```
|
|
64
64
|
|
|
@@ -68,27 +68,27 @@ Objective: Track the pending state of the async `fetchItems()` action to tell th
|
|
|
68
68
|
|
|
69
69
|
```diff
|
|
70
70
|
- withState(fetchItems())
|
|
71
|
-
+ withState(fetchItems(), {silent: true})
|
|
71
|
+
+ withState(fetchItems(), { silent: true })
|
|
72
72
|
```
|
|
73
73
|
|
|
74
74
|
🔹 Revealing the action's pending state after a delay (e.g. to avoid flashing a process indicator when the action is likely to complete by the end of the delay):
|
|
75
75
|
|
|
76
76
|
```diff
|
|
77
77
|
- withState(fetchItems())
|
|
78
|
-
+ withState(fetchItems(), {delay: 500})
|
|
78
|
+
+ withState(fetchItems(), { delay: 500 })
|
|
79
79
|
```
|
|
80
80
|
|
|
81
81
|
🔹 Allowing the action's Promise value to reject explicitly (e.g. in order to provide the action with a custom rejection handler) along with exposing `state.error` that goes by default:
|
|
82
82
|
|
|
83
83
|
```diff
|
|
84
84
|
- withState(fetchItems())
|
|
85
|
-
+ withState(fetchItems(), {throws: true}).catch(handleError)
|
|
85
|
+
+ withState(fetchItems(), { throws: true }).catch(handleError)
|
|
86
86
|
```
|
|
87
87
|
|
|
88
88
|
🔹 Providing an isolated instance of initial shared action state, e.g. for tests or SSR (it can be unnecessary for client-side rendering where the default context value is sufficient, but it can also be used to separate action states of larger self-contained portions of a web app):
|
|
89
89
|
|
|
90
90
|
```diff
|
|
91
|
-
+ import {PendingStateProvider} from
|
|
91
|
+
+ import { PendingStateProvider } from "@t8/react-pending";
|
|
92
92
|
|
|
93
93
|
- <App/>
|
|
94
94
|
+ <PendingStateProvider>
|
|
@@ -100,7 +100,7 @@ Objective: Track the pending state of the async `fetchItems()` action to tell th
|
|
|
100
100
|
|
|
101
101
|
```diff
|
|
102
102
|
+ const initialState = {
|
|
103
|
-
+
|
|
103
|
+
+ "fetch-items": { initialized: true, complete: true },
|
|
104
104
|
+ };
|
|
105
105
|
|
|
106
106
|
- <PendingStateProvider>
|
|
@@ -109,4 +109,4 @@ Objective: Track the pending state of the async `fetchItems()` action to tell th
|
|
|
109
109
|
</PendingStateProvider>
|
|
110
110
|
```
|
|
111
111
|
|
|
112
|
-
With an explicit value or without, the `<PendingStateProvider>`'s nested components will only respond to updates in the particular action states they subscribed to by means of `usePendingState(
|
|
112
|
+
With an explicit value or without, the `<PendingStateProvider>`'s nested components will only respond to updates in the particular action states they subscribed to by means of `usePendingState("action-key")`.
|
package/dist/index.js
CHANGED
|
@@ -78,10 +78,7 @@ var PendingStateProvider = ({
|
|
|
78
78
|
if (value instanceof Map) return value;
|
|
79
79
|
if (typeof value === "object" && value !== null)
|
|
80
80
|
return new Map(
|
|
81
|
-
Object.entries(value).map(([key, state]) => [
|
|
82
|
-
key,
|
|
83
|
-
new Store(state)
|
|
84
|
-
])
|
|
81
|
+
Object.entries(value).map(([key, state]) => [key, new Store(state)])
|
|
85
82
|
);
|
|
86
83
|
if (defaultValueRef.current === null)
|
|
87
84
|
defaultValueRef.current = /* @__PURE__ */ new Map();
|
|
@@ -140,16 +137,14 @@ function usePendingState(store) {
|
|
|
140
137
|
}, delay);
|
|
141
138
|
}
|
|
142
139
|
return value.then((resolvedValue) => {
|
|
143
|
-
if (delayedPending !== null)
|
|
144
|
-
clearTimeout(delayedPending);
|
|
140
|
+
if (delayedPending !== null) clearTimeout(delayedPending);
|
|
145
141
|
setState((prevState) => ({
|
|
146
142
|
...prevState,
|
|
147
143
|
...createState(true, true)
|
|
148
144
|
}));
|
|
149
145
|
return resolvedValue;
|
|
150
146
|
}).catch((error) => {
|
|
151
|
-
if (delayedPending !== null)
|
|
152
|
-
clearTimeout(delayedPending);
|
|
147
|
+
if (delayedPending !== null) clearTimeout(delayedPending);
|
|
153
148
|
setState((prevState) => ({
|
|
154
149
|
...prevState,
|
|
155
150
|
...createState(true, true, error)
|
package/index.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export * from
|
|
2
|
-
export * from
|
|
3
|
-
export * from
|
|
4
|
-
export * from
|
|
1
|
+
export * from "./src/PendingState";
|
|
2
|
+
export * from "./src/PendingStateContext";
|
|
3
|
+
export * from "./src/PendingStateProvider";
|
|
4
|
+
export * from "./src/usePendingState";
|
package/package.json
CHANGED
|
@@ -1,39 +1,46 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@t8/react-pending",
|
|
3
|
-
"version": "1.0.
|
|
4
|
-
"description": "Concise async action state tracking for React apps",
|
|
5
|
-
"main": "dist/index.js",
|
|
6
|
-
"type": "module",
|
|
7
|
-
"scripts": {
|
|
8
|
-
"build": "npx npm-run-all clean compile",
|
|
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
|
-
"
|
|
12
|
-
"
|
|
13
|
-
"
|
|
14
|
-
"
|
|
15
|
-
"
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
"
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
"
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
"@
|
|
38
|
-
|
|
39
|
-
|
|
1
|
+
{
|
|
2
|
+
"name": "@t8/react-pending",
|
|
3
|
+
"version": "1.0.14",
|
|
4
|
+
"description": "Concise async action state tracking for React apps",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"build": "npx npm-run-all clean compile",
|
|
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
|
+
"demo": "npx @t8/serve 3000 * tests/async_status -b src/index.tsx",
|
|
12
|
+
"gh-pages": "npx ghstage --theme=t8 --ymid=103784239 --nav=https://raw.githubusercontent.com/t8js/t8js.github.io/refs/heads/main/assets/nav.html",
|
|
13
|
+
"prepublishOnly": "npx npm-run-all build gh-pages",
|
|
14
|
+
"preversion": "npx npm-run-all typecheck shape build test",
|
|
15
|
+
"shape": "npx codeshape",
|
|
16
|
+
"test": "npx playwright test --project=chromium",
|
|
17
|
+
"typecheck": "tsc --noEmit"
|
|
18
|
+
},
|
|
19
|
+
"author": "axtk",
|
|
20
|
+
"license": "ISC",
|
|
21
|
+
"repository": {
|
|
22
|
+
"type": "git",
|
|
23
|
+
"url": "git+https://github.com/t8js/react-pending.git"
|
|
24
|
+
},
|
|
25
|
+
"homepage": "https://t8.js.org/react-pending",
|
|
26
|
+
"keywords": [
|
|
27
|
+
"async actions",
|
|
28
|
+
"pending state",
|
|
29
|
+
"react"
|
|
30
|
+
],
|
|
31
|
+
"peerDependencies": {
|
|
32
|
+
"react": ">=16.8"
|
|
33
|
+
},
|
|
34
|
+
"devDependencies": {
|
|
35
|
+
"@playwright/test": "^1.55.1",
|
|
36
|
+
"@t8/serve": "^0.1.19",
|
|
37
|
+
"@types/node": "^24.5.2",
|
|
38
|
+
"@types/react": "^19.1.10",
|
|
39
|
+
"@types/react-dom": "^19.1.9",
|
|
40
|
+
"react-dom": "^19.1.1",
|
|
41
|
+
"typescript": "^5.9.2"
|
|
42
|
+
},
|
|
43
|
+
"dependencies": {
|
|
44
|
+
"@t8/react-store": "^1.0.15"
|
|
45
|
+
}
|
|
46
|
+
}
|
package/src/PendingState.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export type PendingState = {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
2
|
+
initialized?: boolean | undefined;
|
|
3
|
+
complete?: boolean | undefined;
|
|
4
|
+
time?: number | undefined;
|
|
5
|
+
error?: unknown;
|
|
6
6
|
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import type {Store} from
|
|
2
|
-
import {createContext} from
|
|
3
|
-
import type {PendingState} from
|
|
1
|
+
import type { Store } from "@t8/react-store";
|
|
2
|
+
import { createContext } from "react";
|
|
3
|
+
import type { PendingState } from "./PendingState";
|
|
4
4
|
|
|
5
5
|
export const PendingStateContext = createContext(
|
|
6
|
-
|
|
6
|
+
new Map<string, Store<PendingState>>(),
|
|
7
7
|
);
|
|
@@ -1,43 +1,40 @@
|
|
|
1
|
-
import {Store} from
|
|
2
|
-
import {type ReactNode, useMemo, useRef} from
|
|
3
|
-
import type {PendingState} from
|
|
4
|
-
import {PendingStateContext} from
|
|
1
|
+
import { Store } from "@t8/react-store";
|
|
2
|
+
import { type ReactNode, useMemo, useRef } from "react";
|
|
3
|
+
import type { PendingState } from "./PendingState";
|
|
4
|
+
import { PendingStateContext } from "./PendingStateContext";
|
|
5
5
|
|
|
6
6
|
export type PendingStateProviderProps = {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
7
|
+
value?:
|
|
8
|
+
| Record<string, PendingState>
|
|
9
|
+
| Map<string, Store<PendingState>>
|
|
10
|
+
| null
|
|
11
|
+
| undefined;
|
|
12
|
+
children?: ReactNode;
|
|
13
13
|
};
|
|
14
14
|
|
|
15
15
|
export const PendingStateProvider = ({
|
|
16
|
-
|
|
17
|
-
|
|
16
|
+
value,
|
|
17
|
+
children,
|
|
18
18
|
}: PendingStateProviderProps) => {
|
|
19
|
-
|
|
19
|
+
let defaultValueRef = useRef<Map<string, Store<PendingState>> | null>(null);
|
|
20
20
|
|
|
21
|
-
|
|
22
|
-
|
|
21
|
+
let resolvedValue = useMemo(() => {
|
|
22
|
+
if (value instanceof Map) return value;
|
|
23
23
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
new Store(state),
|
|
29
|
-
]),
|
|
30
|
-
);
|
|
24
|
+
if (typeof value === "object" && value !== null)
|
|
25
|
+
return new Map(
|
|
26
|
+
Object.entries(value).map(([key, state]) => [key, new Store(state)]),
|
|
27
|
+
);
|
|
31
28
|
|
|
32
|
-
|
|
33
|
-
|
|
29
|
+
if (defaultValueRef.current === null)
|
|
30
|
+
defaultValueRef.current = new Map<string, Store<PendingState>>();
|
|
34
31
|
|
|
35
|
-
|
|
36
|
-
|
|
32
|
+
return defaultValueRef.current;
|
|
33
|
+
}, [value]);
|
|
37
34
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
35
|
+
return (
|
|
36
|
+
<PendingStateContext.Provider value={resolvedValue}>
|
|
37
|
+
{children}
|
|
38
|
+
</PendingStateContext.Provider>
|
|
39
|
+
);
|
|
43
40
|
};
|
package/src/usePendingState.ts
CHANGED
|
@@ -1,25 +1,25 @@
|
|
|
1
|
-
import {isStore, type SetStoreState, Store, useStore} from
|
|
2
|
-
import {useCallback, useContext, useMemo, useRef, useState} from
|
|
3
|
-
import type {PendingState} from
|
|
4
|
-
import {PendingStateContext} from
|
|
1
|
+
import { isStore, type SetStoreState, Store, useStore } from "@t8/react-store";
|
|
2
|
+
import { useCallback, useContext, useMemo, useRef, useState } from "react";
|
|
3
|
+
import type { PendingState } from "./PendingState";
|
|
4
|
+
import { PendingStateContext } from "./PendingStateContext";
|
|
5
5
|
|
|
6
6
|
function createState(
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
initialized = false,
|
|
8
|
+
complete = false,
|
|
9
|
+
error?: unknown,
|
|
10
10
|
): PendingState {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
11
|
+
return {
|
|
12
|
+
initialized,
|
|
13
|
+
complete,
|
|
14
|
+
error,
|
|
15
|
+
time: Date.now(),
|
|
16
|
+
};
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
export type WithStateOptions = {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
20
|
+
silent?: boolean;
|
|
21
|
+
throws?: boolean;
|
|
22
|
+
delay?: number;
|
|
23
23
|
};
|
|
24
24
|
|
|
25
25
|
/**
|
|
@@ -32,98 +32,96 @@ export type WithStateOptions = {
|
|
|
32
32
|
* - `setState()` to directly update the state.
|
|
33
33
|
*/
|
|
34
34
|
export function usePendingState(
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
35
|
+
/**
|
|
36
|
+
* A unique store key or a store. Providing a store key or a
|
|
37
|
+
* shared store allows to share the state across multiple
|
|
38
|
+
* components.
|
|
39
|
+
*/
|
|
40
|
+
store?: string | Store<PendingState> | null,
|
|
41
41
|
): [PendingState, <T>(value: T) => T, SetStoreState<PendingState>] {
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
42
|
+
let storeMap = useContext(PendingStateContext);
|
|
43
|
+
let storeRef = useRef<Store<PendingState> | null>(null);
|
|
44
|
+
let [storeItemInited, setStoreItemInited] = useState(false);
|
|
45
45
|
|
|
46
|
-
|
|
47
|
-
|
|
46
|
+
let resolvedStore = useMemo(() => {
|
|
47
|
+
if (isStore<PendingState>(store)) return store;
|
|
48
48
|
|
|
49
|
-
|
|
50
|
-
|
|
49
|
+
if (typeof store === "string") {
|
|
50
|
+
let storeItem = storeMap.get(store);
|
|
51
51
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
52
|
+
if (!storeItem) {
|
|
53
|
+
storeItem = new Store(createState());
|
|
54
|
+
storeMap.set(store, storeItem);
|
|
55
55
|
|
|
56
|
-
|
|
57
|
-
|
|
56
|
+
if (!storeItemInited) setStoreItemInited(true);
|
|
57
|
+
}
|
|
58
58
|
|
|
59
|
-
|
|
60
|
-
|
|
59
|
+
return storeItem;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
if (!storeRef.current) storeRef.current = new Store(createState());
|
|
63
|
+
|
|
64
|
+
return storeRef.current;
|
|
65
|
+
}, [store, storeMap, storeItemInited]);
|
|
66
|
+
|
|
67
|
+
let [state, setState] = useStore(resolvedStore);
|
|
61
68
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
setState(prevState => ({
|
|
79
|
-
...prevState,
|
|
80
|
-
...createState(true, false),
|
|
81
|
-
}));
|
|
82
|
-
else
|
|
83
|
-
delayedPending = setTimeout(() => {
|
|
84
|
-
setState(prevState => ({
|
|
85
|
-
...prevState,
|
|
86
|
-
...createState(true, false),
|
|
87
|
-
}));
|
|
88
|
-
|
|
89
|
-
delayedPending = null;
|
|
90
|
-
}, delay);
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
return value
|
|
94
|
-
.then(resolvedValue => {
|
|
95
|
-
if (delayedPending !== null)
|
|
96
|
-
clearTimeout(delayedPending);
|
|
97
|
-
|
|
98
|
-
setState(prevState => ({
|
|
99
|
-
...prevState,
|
|
100
|
-
...createState(true, true),
|
|
101
|
-
}));
|
|
102
|
-
|
|
103
|
-
return resolvedValue;
|
|
104
|
-
})
|
|
105
|
-
.catch(error => {
|
|
106
|
-
if (delayedPending !== null)
|
|
107
|
-
clearTimeout(delayedPending);
|
|
108
|
-
|
|
109
|
-
setState(prevState => ({
|
|
110
|
-
...prevState,
|
|
111
|
-
...createState(true, true, error),
|
|
112
|
-
}));
|
|
113
|
-
|
|
114
|
-
if (options?.throws) throw error;
|
|
115
|
-
}) as T;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
setState(prevState => ({
|
|
69
|
+
let withState = useCallback(
|
|
70
|
+
<T>(value: T, options?: WithStateOptions): T => {
|
|
71
|
+
if (value instanceof Promise) {
|
|
72
|
+
let delayedPending: ReturnType<typeof setTimeout> | null = null;
|
|
73
|
+
|
|
74
|
+
if (!options?.silent) {
|
|
75
|
+
let delay = options?.delay;
|
|
76
|
+
|
|
77
|
+
if (delay === undefined)
|
|
78
|
+
setState((prevState) => ({
|
|
79
|
+
...prevState,
|
|
80
|
+
...createState(true, false),
|
|
81
|
+
}));
|
|
82
|
+
else
|
|
83
|
+
delayedPending = setTimeout(() => {
|
|
84
|
+
setState((prevState) => ({
|
|
119
85
|
...prevState,
|
|
120
|
-
...createState(true,
|
|
86
|
+
...createState(true, false),
|
|
87
|
+
}));
|
|
88
|
+
|
|
89
|
+
delayedPending = null;
|
|
90
|
+
}, delay);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
return value
|
|
94
|
+
.then((resolvedValue) => {
|
|
95
|
+
if (delayedPending !== null) clearTimeout(delayedPending);
|
|
96
|
+
|
|
97
|
+
setState((prevState) => ({
|
|
98
|
+
...prevState,
|
|
99
|
+
...createState(true, true),
|
|
100
|
+
}));
|
|
101
|
+
|
|
102
|
+
return resolvedValue;
|
|
103
|
+
})
|
|
104
|
+
.catch((error) => {
|
|
105
|
+
if (delayedPending !== null) clearTimeout(delayedPending);
|
|
106
|
+
|
|
107
|
+
setState((prevState) => ({
|
|
108
|
+
...prevState,
|
|
109
|
+
...createState(true, true, error),
|
|
121
110
|
}));
|
|
122
111
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
112
|
+
if (options?.throws) throw error;
|
|
113
|
+
}) as T;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
setState((prevState) => ({
|
|
117
|
+
...prevState,
|
|
118
|
+
...createState(true, true),
|
|
119
|
+
}));
|
|
120
|
+
|
|
121
|
+
return value;
|
|
122
|
+
},
|
|
123
|
+
[setState],
|
|
124
|
+
);
|
|
127
125
|
|
|
128
|
-
|
|
126
|
+
return [state, withState, setState];
|
|
129
127
|
}
|
package/tsconfig.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"include": ["index.ts", "playwright.config.ts", "src", "tests"],
|
|
3
|
+
"compilerOptions": {
|
|
4
|
+
"lib": ["ESNext", "DOM"],
|
|
5
|
+
"target": "ESNext",
|
|
6
|
+
"outDir": "dist",
|
|
7
|
+
"moduleResolution": "node",
|
|
8
|
+
"jsx": "react-jsx",
|
|
9
|
+
"strict": true,
|
|
10
|
+
"noUnusedLocals": true,
|
|
11
|
+
"noUnusedParameters": true
|
|
12
|
+
}
|
|
13
|
+
}
|