rask-ui 0.18.3 → 0.19.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/README.md +4 -1
- package/dist/component.d.ts.map +1 -1
- package/dist/component.js +5 -2
- package/dist/error.d.ts +3 -14
- package/dist/error.d.ts.map +1 -1
- package/dist/error.js +14 -15
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -1
- package/dist/useAction.d.ts +18 -0
- package/dist/useAction.d.ts.map +1 -0
- package/dist/useAction.js +43 -0
- package/dist/useAsync.d.ts +26 -20
- package/dist/useAsync.d.ts.map +1 -1
- package/dist/useAsync.js +100 -41
- package/dist/useCatchError.d.ts +5 -0
- package/dist/useCatchError.d.ts.map +1 -0
- package/dist/useCatchError.js +16 -0
- package/dist/useSuspend.d.ts +40 -0
- package/dist/useSuspend.d.ts.map +1 -0
- package/dist/useSuspend.js +48 -0
- package/dist/useSuspendAsync.d.ts +18 -0
- package/dist/useSuspendAsync.d.ts.map +1 -0
- package/dist/useSuspendAsync.js +37 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -48,7 +48,10 @@ RASK provides a set of reactive hooks for building interactive UIs. These hooks
|
|
|
48
48
|
- **`useState`** - Create reactive state objects
|
|
49
49
|
- **`useEffect`** - Run side effects when dependencies change
|
|
50
50
|
- **`useDerived`** - Derive values from state with automatic caching
|
|
51
|
-
- **`useAsync`** -
|
|
51
|
+
- **`useAsync`** - Fetch async values with automatic observation and cancellation
|
|
52
|
+
- **`useAction`** - Perform async operations with queuing and retry support
|
|
53
|
+
- **`useSuspend`** - Suspend until multiple async values resolve
|
|
54
|
+
- **`useCatchError`** - Catch and handle component errors (hook-based error boundary)
|
|
52
55
|
- **`useRouter`** - Type-safe client-side routing
|
|
53
56
|
- **`createContext`** / **`useContext`** - Share data through the component tree
|
|
54
57
|
- **`useView`** - Compose state and methods into reusable objects
|
package/dist/component.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"component.d.ts","sourceRoot":"","sources":["../src/component.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,EACL,SAAS,EACT,KAAK,EACL,WAAW,EACZ,MAAM,SAAS,CAAC;AAEjB,OAAO,EAAsB,QAAQ,EAAU,MAAM,eAAe,CAAC;AAIrE,MAAM,MAAM,8BAA8B,CAAC,CAAC,SAAS,KAAK,CAAC,GAAG,CAAC,IAC3D,CAAC,MAAM,KAAK,CAAC,GACb,CAAC,CAAC,KAAK,EAAE,CAAC,KAAK,KAAK,CAAC,CAAC;AAE1B,qBAAa,sBAAuB,SAAQ,SAAS;IAC3C,QAAQ,EAAE,8BAA8B,CAAC,GAAG,CAAC,CAAC;IACtD,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,aAAa,CAAS;IAC9B,QAAQ,WAML;IACH,OAAO,CAAC,aAAa,CAAc;IAEnC,qBAAqB,IAAI,OAAO;IAMhC,kBAAkB,IAAI,IAAI;IAG1B,yBAAyB,CAAC,SAAS,EAAE,GAAG,GAAG,IAAI;IAe/C,MAAM;CAOP;AAID,wBAAgB,mBAAmB,2CAElC;AAED,wBAAgB,cAAc,CAAC,EAAE,EAAE,MAAM,IAAI,QAM5C;AAED,wBAAgB,UAAU,CAAC,EAAE,EAAE,MAAM,IAAI,QAMxC;AAED,MAAM,MAAM,6BAA6B,CAAC,CAAC,SAAS,KAAK,CAAC,GAAG,CAAC,IAC1D,CAAC,MAAM,MAAM,KAAK,CAAC,GACnB,CAAC,CAAC,KAAK,EAAE,CAAC,KAAK,MAAM,KAAK,CAAC,CAAC;AAEhC,qBAAa,qBAAqB,CAAC,CAAC,SAAS,KAAK,CAAC,GAAG,CAAC,CAAE,SAAQ,SAAS,CAAC,CAAC,CAAC;IACnE,KAAK,EAAE,6BAA6B,CAAC,CAAC,CAAC,CAAC;IAChD,OAAO,CAAC,QAAQ,CAAC,CAAc;IAC/B,OAAO,CAAC,aAAa,CAAC,CAAa;IAwBnC,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,aAAa,CAAS;IAE9B,QAAQ,WAOL;IAEH,WAAW,UAAS;IACpB,OAAO,EAAE,KAAK,CAAC;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,GAAG,EAAE,MAAM,IAAI,CAAA;KAAE,CAAC,CAAM;IAC3D,QAAQ,gBAAa;IACrB,eAAe;IAUf,QAAQ,EAAE,KAAK,CAAC,MAAM,IAAI,CAAC,CAAM;IACjC,UAAU,EAAE,KAAK,CAAC,MAAM,IAAI,CAAC,CAAM;IAEnC,iBAAiB,IAAI,IAAI;IAGzB,oBAAoB,IAAI,IAAI;IAI5B,yBAAyB,CACvB,SAAS,EAAE,QAAQ,CAAC;QAAE,QAAQ,CAAC,EAAE,WAAW,CAAA;KAAE,GAAG,CAAC,CAAC,GAClD,IAAI;IAcP,qBAAqB,IAAI,OAAO;IAMhC,MAAM;
|
|
1
|
+
{"version":3,"file":"component.d.ts","sourceRoot":"","sources":["../src/component.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,EACL,SAAS,EACT,KAAK,EACL,WAAW,EACZ,MAAM,SAAS,CAAC;AAEjB,OAAO,EAAsB,QAAQ,EAAU,MAAM,eAAe,CAAC;AAIrE,MAAM,MAAM,8BAA8B,CAAC,CAAC,SAAS,KAAK,CAAC,GAAG,CAAC,IAC3D,CAAC,MAAM,KAAK,CAAC,GACb,CAAC,CAAC,KAAK,EAAE,CAAC,KAAK,KAAK,CAAC,CAAC;AAE1B,qBAAa,sBAAuB,SAAQ,SAAS;IAC3C,QAAQ,EAAE,8BAA8B,CAAC,GAAG,CAAC,CAAC;IACtD,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,aAAa,CAAS;IAC9B,QAAQ,WAML;IACH,OAAO,CAAC,aAAa,CAAc;IAEnC,qBAAqB,IAAI,OAAO;IAMhC,kBAAkB,IAAI,IAAI;IAG1B,yBAAyB,CAAC,SAAS,EAAE,GAAG,GAAG,IAAI;IAe/C,MAAM;CAOP;AAID,wBAAgB,mBAAmB,2CAElC;AAED,wBAAgB,cAAc,CAAC,EAAE,EAAE,MAAM,IAAI,QAM5C;AAED,wBAAgB,UAAU,CAAC,EAAE,EAAE,MAAM,IAAI,QAMxC;AAED,MAAM,MAAM,6BAA6B,CAAC,CAAC,SAAS,KAAK,CAAC,GAAG,CAAC,IAC1D,CAAC,MAAM,MAAM,KAAK,CAAC,GACnB,CAAC,CAAC,KAAK,EAAE,CAAC,KAAK,MAAM,KAAK,CAAC,CAAC;AAEhC,qBAAa,qBAAqB,CAAC,CAAC,SAAS,KAAK,CAAC,GAAG,CAAC,CAAE,SAAQ,SAAS,CAAC,CAAC,CAAC;IACnE,KAAK,EAAE,6BAA6B,CAAC,CAAC,CAAC,CAAC;IAChD,OAAO,CAAC,QAAQ,CAAC,CAAc;IAC/B,OAAO,CAAC,aAAa,CAAC,CAAa;IAwBnC,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,aAAa,CAAS;IAE9B,QAAQ,WAOL;IAEH,WAAW,UAAS;IACpB,OAAO,EAAE,KAAK,CAAC;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,GAAG,EAAE,MAAM,IAAI,CAAA;KAAE,CAAC,CAAM;IAC3D,QAAQ,gBAAa;IACrB,eAAe;IAUf,QAAQ,EAAE,KAAK,CAAC,MAAM,IAAI,CAAC,CAAM;IACjC,UAAU,EAAE,KAAK,CAAC,MAAM,IAAI,CAAC,CAAM;IAEnC,iBAAiB,IAAI,IAAI;IAGzB,oBAAoB,IAAI,IAAI;IAI5B,yBAAyB,CACvB,SAAS,EAAE,QAAQ,CAAC;QAAE,QAAQ,CAAC,EAAE,WAAW,CAAA;KAAE,GAAG,CAAC,CAAC,GAClD,IAAI;IAcP,qBAAqB,IAAI,OAAO;IAMhC,MAAM;CA6CP;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,EAAE,GAAG,CAAC,EAAE,MAAM,SAO9D"}
|
package/dist/component.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { createComponentVNode, Component, } from "inferno";
|
|
2
2
|
import { getCurrentObserver, Observer, Signal } from "./observation";
|
|
3
3
|
import { syncBatch } from "./batch";
|
|
4
|
+
import { CatchErrorContext } from "./useCatchError";
|
|
4
5
|
export class RaskStatelessComponent extends Component {
|
|
5
6
|
isNotified = false;
|
|
6
7
|
isReconciling = false;
|
|
@@ -157,10 +158,12 @@ export class RaskStatefulComponent extends Component {
|
|
|
157
158
|
this.isRendering = false;
|
|
158
159
|
}
|
|
159
160
|
catch (error) {
|
|
160
|
-
|
|
161
|
+
const notifyError = this.contexts.get(CatchErrorContext) ||
|
|
162
|
+
this.context.getContext?.(CatchErrorContext);
|
|
163
|
+
if (typeof notifyError !== "function") {
|
|
161
164
|
throw error;
|
|
162
165
|
}
|
|
163
|
-
|
|
166
|
+
notifyError(error);
|
|
164
167
|
}
|
|
165
168
|
finally {
|
|
166
169
|
stopObserving();
|
package/dist/error.d.ts
CHANGED
|
@@ -1,16 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
export declare
|
|
3
|
-
children: any;
|
|
4
|
-
error: (error: unknown) => VNode;
|
|
5
|
-
}, {
|
|
1
|
+
export declare const CatchErrorContext: import("./createContext").Context<(error: unknown) => void>;
|
|
2
|
+
export declare function useCatchError(): {
|
|
6
3
|
error: unknown;
|
|
7
|
-
}
|
|
8
|
-
getChildContext(): {
|
|
9
|
-
notifyError: (error: unknown) => void;
|
|
10
|
-
};
|
|
11
|
-
state: {
|
|
12
|
-
error: null;
|
|
13
|
-
};
|
|
14
|
-
render(): any;
|
|
15
|
-
}
|
|
4
|
+
};
|
|
16
5
|
//# sourceMappingURL=error.d.ts.map
|
package/dist/error.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"error.d.ts","sourceRoot":"","sources":["../src/error.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"error.d.ts","sourceRoot":"","sources":["../src/error.tsx"],"names":[],"mappings":"AAIA,eAAO,MAAM,iBAAiB,4CAAyB,OAAO,KAAK,IAAI,CAAG,CAAC;AAE3E,wBAAgB,aAAa;WAQK,OAAO;EAOxC"}
|
package/dist/error.js
CHANGED
|
@@ -1,17 +1,16 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
}
|
|
10
|
-
state = { error: null };
|
|
11
|
-
render() {
|
|
12
|
-
if (this.state.error) {
|
|
13
|
-
return this.props.error(this.state.error);
|
|
14
|
-
}
|
|
15
|
-
return this.props.children;
|
|
1
|
+
import { useState } from "./useState";
|
|
2
|
+
import { createContext, useInjectContext } from "./createContext";
|
|
3
|
+
import { getCurrentComponent } from "./component";
|
|
4
|
+
export const CatchErrorContext = createContext();
|
|
5
|
+
export function useCatchError() {
|
|
6
|
+
const currentComponent = getCurrentComponent();
|
|
7
|
+
if (!currentComponent || currentComponent.isRendering) {
|
|
8
|
+
throw new Error("Only use the useCatchError hook in setup");
|
|
16
9
|
}
|
|
10
|
+
const inject = useInjectContext(CatchErrorContext);
|
|
11
|
+
const state = useState({
|
|
12
|
+
error: null,
|
|
13
|
+
});
|
|
14
|
+
inject((error) => (state.error = error));
|
|
15
|
+
return state;
|
|
17
16
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -3,7 +3,9 @@ export { useCleanup, useMountEffect, RaskStatefulComponent, RaskStatelessCompone
|
|
|
3
3
|
export { createContext, useContext, useInjectContext } from "./createContext";
|
|
4
4
|
export { useState, assignState } from "./useState";
|
|
5
5
|
export { useAsync, Async } from "./useAsync";
|
|
6
|
-
export {
|
|
6
|
+
export { useAction, Action } from "./useAction";
|
|
7
|
+
export { useSuspend } from "./useSuspend";
|
|
8
|
+
export { useCatchError } from "./useCatchError";
|
|
7
9
|
export { useRef } from "./useRef";
|
|
8
10
|
export { useView } from "./useView";
|
|
9
11
|
export { useEffect } from "./useEffect";
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,OAAO,EACL,UAAU,EACV,cAAc,EACd,qBAAqB,EACrB,sBAAsB,GACvB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAC9E,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACnD,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,OAAO,EACL,UAAU,EACV,cAAc,EACd,qBAAqB,EACrB,sBAAsB,GACvB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,aAAa,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAC9E,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACnD,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAChD,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAClC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACnD,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACpC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAGhD,OAAO,EACL,WAAW,EACX,oBAAoB,EACpB,cAAc,EACd,eAAe,EACf,cAAc,EACd,SAAS,GACV,MAAM,SAAS,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -3,7 +3,9 @@ export { useCleanup, useMountEffect, RaskStatefulComponent, RaskStatelessCompone
|
|
|
3
3
|
export { createContext, useContext, useInjectContext } from "./createContext";
|
|
4
4
|
export { useState, assignState } from "./useState";
|
|
5
5
|
export { useAsync } from "./useAsync";
|
|
6
|
-
export {
|
|
6
|
+
export { useAction } from "./useAction";
|
|
7
|
+
export { useSuspend } from "./useSuspend";
|
|
8
|
+
export { useCatchError } from "./useCatchError";
|
|
7
9
|
export { useRef } from "./useRef";
|
|
8
10
|
export { useView } from "./useView";
|
|
9
11
|
export { useEffect } from "./useEffect";
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export type QueuedAction<P> = {
|
|
2
|
+
params: P;
|
|
3
|
+
error: Error | null;
|
|
4
|
+
retry(): void;
|
|
5
|
+
cancel(): void;
|
|
6
|
+
};
|
|
7
|
+
export type ActionState<P> = {
|
|
8
|
+
isPending: boolean;
|
|
9
|
+
queue: QueuedAction<P>[];
|
|
10
|
+
};
|
|
11
|
+
export type Action<P = null> = [
|
|
12
|
+
ActionState<P>,
|
|
13
|
+
[
|
|
14
|
+
P
|
|
15
|
+
] extends [null] ? () => void : (params: P) => void
|
|
16
|
+
];
|
|
17
|
+
export declare function useAction<P = null>(fn: [P] extends [null] ? () => Promise<void> : (params: P) => Promise<void>): Action<P>;
|
|
18
|
+
//# sourceMappingURL=useAction.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useAction.d.ts","sourceRoot":"","sources":["../src/useAction.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,YAAY,CAAC,CAAC,IAAI;IAC5B,MAAM,EAAE,CAAC,CAAC;IACV,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IACpB,KAAK,IAAI,IAAI,CAAC;IACd,MAAM,IAAI,IAAI,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,WAAW,CAAC,CAAC,IAAI;IAC3B,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,EAAE,YAAY,CAAC,CAAC,CAAC,EAAE,CAAC;CAC1B,CAAC;AAEF,MAAM,MAAM,MAAM,CAAC,CAAC,GAAG,IAAI,IAAI;IAC7B,WAAW,CAAC,CAAC,CAAC;IACd;QAAC,CAAC;KAAC,SAAS,CAAC,IAAI,CAAC,GAAG,MAAM,IAAI,GAAG,CAAC,MAAM,EAAE,CAAC,KAAK,IAAI;CACtD,CAAC;AAEF,wBAAgB,SAAS,CAAC,CAAC,GAAG,IAAI,EAChC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,GAC1E,MAAM,CAAC,CAAC,CAAC,CAkDX"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { useState } from "./useState";
|
|
2
|
+
export function useAction(fn) {
|
|
3
|
+
const state = useState({
|
|
4
|
+
isPending: false,
|
|
5
|
+
queue: [],
|
|
6
|
+
});
|
|
7
|
+
const processQueue = () => {
|
|
8
|
+
const next = state.queue[0];
|
|
9
|
+
if (!next) {
|
|
10
|
+
state.isPending = false;
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
state.isPending = true;
|
|
14
|
+
fn(next.params)
|
|
15
|
+
.then(() => {
|
|
16
|
+
state.queue.shift();
|
|
17
|
+
processQueue();
|
|
18
|
+
})
|
|
19
|
+
.catch((error) => {
|
|
20
|
+
next.error = error;
|
|
21
|
+
});
|
|
22
|
+
};
|
|
23
|
+
const run = (params) => {
|
|
24
|
+
params = (params || null);
|
|
25
|
+
let actionProxy;
|
|
26
|
+
const index = state.queue.push({
|
|
27
|
+
params,
|
|
28
|
+
error: null,
|
|
29
|
+
retry() {
|
|
30
|
+
processQueue();
|
|
31
|
+
},
|
|
32
|
+
cancel() {
|
|
33
|
+
state.queue.splice(state.queue.indexOf(actionProxy), 1);
|
|
34
|
+
processQueue();
|
|
35
|
+
},
|
|
36
|
+
}) - 1;
|
|
37
|
+
actionProxy = state.queue[index];
|
|
38
|
+
if (index === 0) {
|
|
39
|
+
processQueue();
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
return [state, run];
|
|
43
|
+
}
|
package/dist/useAsync.d.ts
CHANGED
|
@@ -1,27 +1,33 @@
|
|
|
1
|
-
export type AsyncState<
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
export type AsyncState<T> = {
|
|
2
|
+
error: Error;
|
|
3
|
+
isLoading: true;
|
|
4
|
+
isRefreshing: false;
|
|
5
|
+
value: null;
|
|
6
|
+
} | {
|
|
7
|
+
error: Error;
|
|
8
|
+
isLoading: false;
|
|
9
|
+
isRefreshing: true;
|
|
10
|
+
value: T;
|
|
6
11
|
} | {
|
|
7
|
-
isPending: true;
|
|
8
|
-
value: T | I;
|
|
9
|
-
params: P;
|
|
10
12
|
error: null;
|
|
13
|
+
isLoading: true;
|
|
14
|
+
isRefreshing: false;
|
|
15
|
+
value: null;
|
|
11
16
|
} | {
|
|
12
|
-
isPending: false;
|
|
13
|
-
params: null;
|
|
14
|
-
value: T;
|
|
15
17
|
error: null;
|
|
18
|
+
isLoading: false;
|
|
19
|
+
isRefreshing: true;
|
|
20
|
+
value: T;
|
|
16
21
|
} | {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
22
|
+
error: null;
|
|
23
|
+
isLoading: false;
|
|
24
|
+
isRefreshing: false;
|
|
25
|
+
value: T;
|
|
21
26
|
};
|
|
22
|
-
export type Async<
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
export declare function
|
|
27
|
+
export type Async<T extends NonNullable<any>> = [
|
|
28
|
+
AsyncState<T>,
|
|
29
|
+
() => Promise<void>
|
|
30
|
+
];
|
|
31
|
+
export declare function isAsync(value: unknown): boolean;
|
|
32
|
+
export declare function useAsync<T extends NonNullable<any>>(fn: (signal?: AbortSignal) => Promise<T>): Async<T>;
|
|
27
33
|
//# sourceMappingURL=useAsync.d.ts.map
|
package/dist/useAsync.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useAsync.d.ts","sourceRoot":"","sources":["../src/useAsync.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"useAsync.d.ts","sourceRoot":"","sources":["../src/useAsync.ts"],"names":[],"mappings":"AAKA,MAAM,MAAM,UAAU,CAAC,CAAC,IACpB;IACE,KAAK,EAAE,KAAK,CAAC;IACb,SAAS,EAAE,IAAI,CAAC;IAChB,YAAY,EAAE,KAAK,CAAC;IACpB,KAAK,EAAE,IAAI,CAAC;CACb,GACD;IACE,KAAK,EAAE,KAAK,CAAC;IACb,SAAS,EAAE,KAAK,CAAC;IACjB,YAAY,EAAE,IAAI,CAAC;IACnB,KAAK,EAAE,CAAC,CAAC;CACV,GACD;IACE,KAAK,EAAE,IAAI,CAAC;IACZ,SAAS,EAAE,IAAI,CAAC;IAChB,YAAY,EAAE,KAAK,CAAC;IACpB,KAAK,EAAE,IAAI,CAAC;CACb,GACD;IACE,KAAK,EAAE,IAAI,CAAC;IACZ,SAAS,EAAE,KAAK,CAAC;IACjB,YAAY,EAAE,IAAI,CAAC;IACnB,KAAK,EAAE,CAAC,CAAC;CACV,GACD;IACE,KAAK,EAAE,IAAI,CAAC;IACZ,SAAS,EAAE,KAAK,CAAC;IACjB,YAAY,EAAE,KAAK,CAAC;IACpB,KAAK,EAAE,CAAC,CAAC;CACV,CAAC;AAEN,MAAM,MAAM,KAAK,CAAC,CAAC,SAAS,WAAW,CAAC,GAAG,CAAC,IAAI;IAC9C,UAAU,CAAC,CAAC,CAAC;IACb,MAAM,OAAO,CAAC,IAAI,CAAC;CACpB,CAAC;AAEF,wBAAgB,OAAO,CAAC,KAAK,EAAE,OAAO,WAWrC;AAED,wBAAgB,QAAQ,CAAC,CAAC,SAAS,WAAW,CAAC,GAAG,CAAC,EACjD,EAAE,EAAE,CAAC,MAAM,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,CAAC,CAAC,GA0InC,KAAK,CAAC,CAAC,CAAC,CACd"}
|
package/dist/useAsync.js
CHANGED
|
@@ -1,72 +1,131 @@
|
|
|
1
|
+
import { syncBatch } from "./batch";
|
|
1
2
|
import { useCleanup, getCurrentComponent } from "./component";
|
|
3
|
+
import { Observer } from "./observation";
|
|
2
4
|
import { assignState, useState } from "./useState";
|
|
3
|
-
export function
|
|
5
|
+
export function isAsync(value) {
|
|
6
|
+
if (value === null || typeof value !== "object") {
|
|
7
|
+
return false;
|
|
8
|
+
}
|
|
9
|
+
return Boolean("isLoading" in value &&
|
|
10
|
+
"isRefreshing" in value &&
|
|
11
|
+
"error" in value &&
|
|
12
|
+
"value" in value);
|
|
13
|
+
}
|
|
14
|
+
export function useAsync(fn) {
|
|
4
15
|
const currentComponent = getCurrentComponent();
|
|
5
16
|
if (!currentComponent || currentComponent.isRendering) {
|
|
6
|
-
throw new Error("Only use
|
|
17
|
+
throw new Error("Only use useAsync in component setup");
|
|
7
18
|
}
|
|
8
|
-
const value = args.length === 2 ? args[0] : null;
|
|
9
|
-
const fn = args.length === 2 ? args[1] : args[0];
|
|
10
19
|
const state = useState({
|
|
11
|
-
|
|
12
|
-
|
|
20
|
+
isLoading: true,
|
|
21
|
+
isRefreshing: false,
|
|
22
|
+
value: null,
|
|
13
23
|
error: null,
|
|
14
|
-
params: null,
|
|
15
24
|
});
|
|
25
|
+
const refreshResolvers = [];
|
|
16
26
|
let currentAbortController;
|
|
17
|
-
const
|
|
27
|
+
const refresh = () => {
|
|
18
28
|
currentAbortController?.abort();
|
|
19
29
|
const abortController = (currentAbortController = new AbortController());
|
|
20
|
-
const
|
|
30
|
+
const stopObserving = observer.observe();
|
|
31
|
+
const promise = fn(abortController.signal);
|
|
32
|
+
stopObserving();
|
|
21
33
|
promise
|
|
22
34
|
.then((result) => {
|
|
23
35
|
if (abortController.signal.aborted) {
|
|
24
36
|
return;
|
|
25
37
|
}
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
38
|
+
syncBatch(() => {
|
|
39
|
+
assignState(state, {
|
|
40
|
+
isLoading: false,
|
|
41
|
+
isRefreshing: false,
|
|
42
|
+
value: result,
|
|
43
|
+
error: null,
|
|
44
|
+
});
|
|
31
45
|
});
|
|
46
|
+
refreshResolvers.forEach((resolver) => resolver.resolve());
|
|
47
|
+
refreshResolvers.length = 0;
|
|
32
48
|
})
|
|
33
49
|
.catch((error) => {
|
|
34
50
|
if (abortController.signal.aborted) {
|
|
35
51
|
return;
|
|
36
52
|
}
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
53
|
+
syncBatch(() => {
|
|
54
|
+
assignState(state, {
|
|
55
|
+
isLoading: state.isLoading,
|
|
56
|
+
isRefreshing: state.isRefreshing,
|
|
57
|
+
value: state.value,
|
|
58
|
+
error,
|
|
59
|
+
});
|
|
42
60
|
});
|
|
61
|
+
refreshResolvers.forEach((resolver) => resolver.reject(error));
|
|
62
|
+
refreshResolvers.length = 0;
|
|
43
63
|
});
|
|
44
64
|
return promise;
|
|
45
65
|
};
|
|
46
|
-
|
|
66
|
+
const observer = new Observer(() => {
|
|
67
|
+
syncBatch(() => {
|
|
68
|
+
if (state.isLoading) {
|
|
69
|
+
refresh();
|
|
70
|
+
}
|
|
71
|
+
else if (state.error && state.value === null) {
|
|
72
|
+
assignState(state, {
|
|
73
|
+
isLoading: true,
|
|
74
|
+
isRefreshing: false,
|
|
75
|
+
value: state.value,
|
|
76
|
+
error: null,
|
|
77
|
+
});
|
|
78
|
+
refresh();
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
assignState(state, {
|
|
82
|
+
isLoading: false,
|
|
83
|
+
isRefreshing: true,
|
|
84
|
+
value: state.value,
|
|
85
|
+
error: null,
|
|
86
|
+
});
|
|
87
|
+
refresh();
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
useCleanup(() => {
|
|
92
|
+
currentAbortController?.abort();
|
|
93
|
+
observer.dispose();
|
|
94
|
+
});
|
|
95
|
+
refresh();
|
|
47
96
|
return [
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
97
|
+
state,
|
|
98
|
+
async () => {
|
|
99
|
+
if (state.isLoading && !state.error) {
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
syncBatch(() => {
|
|
103
|
+
if (state.error && state.value === null) {
|
|
104
|
+
assignState(state, {
|
|
105
|
+
isLoading: true,
|
|
106
|
+
isRefreshing: false,
|
|
107
|
+
value: state.value,
|
|
108
|
+
error: null,
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
else {
|
|
112
|
+
assignState(state, {
|
|
113
|
+
isLoading: false,
|
|
114
|
+
isRefreshing: true,
|
|
115
|
+
value: state.value,
|
|
116
|
+
error: null,
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
});
|
|
120
|
+
let resolve;
|
|
121
|
+
let reject;
|
|
122
|
+
const promise = new Promise((res, rej) => {
|
|
123
|
+
resolve = res;
|
|
124
|
+
reject = rej;
|
|
69
125
|
});
|
|
126
|
+
refreshResolvers.push({ resolve, reject });
|
|
127
|
+
refresh();
|
|
128
|
+
return promise;
|
|
70
129
|
},
|
|
71
130
|
];
|
|
72
131
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useCatchError.d.ts","sourceRoot":"","sources":["../src/useCatchError.tsx"],"names":[],"mappings":"AAIA,eAAO,MAAM,iBAAiB,4CAAyB,OAAO,KAAK,IAAI,CAAG,CAAC;AAE3E,wBAAgB,aAAa;WAQK,OAAO;EAOxC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { useState } from "./useState";
|
|
2
|
+
import { createContext, useInjectContext } from "./createContext";
|
|
3
|
+
import { getCurrentComponent } from "./component";
|
|
4
|
+
export const CatchErrorContext = createContext();
|
|
5
|
+
export function useCatchError() {
|
|
6
|
+
const currentComponent = getCurrentComponent();
|
|
7
|
+
if (!currentComponent || currentComponent.isRendering) {
|
|
8
|
+
throw new Error("Only use the useCatchError hook in setup");
|
|
9
|
+
}
|
|
10
|
+
const inject = useInjectContext(CatchErrorContext);
|
|
11
|
+
const state = useState({
|
|
12
|
+
error: null,
|
|
13
|
+
});
|
|
14
|
+
inject((error) => (state.error = error));
|
|
15
|
+
return state;
|
|
16
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { AsyncState } from "./useAsync";
|
|
2
|
+
type SuspendState<T extends Record<string, () => any>> = {
|
|
3
|
+
error: Error;
|
|
4
|
+
isLoading: true;
|
|
5
|
+
isRefreshing: false;
|
|
6
|
+
values: {
|
|
7
|
+
[K in keyof T]: ReturnType<T[K]> extends AsyncState<any> ? ReturnType<T[K]>["value"] : ReturnType<T[K]>;
|
|
8
|
+
};
|
|
9
|
+
} | {
|
|
10
|
+
error: Error;
|
|
11
|
+
isLoading: false;
|
|
12
|
+
isRefreshing: true;
|
|
13
|
+
values: {
|
|
14
|
+
[K in keyof T]: ReturnType<T[K]> extends AsyncState<any> ? NonNullable<ReturnType<T[K]>["value"]> : ReturnType<T[K]>;
|
|
15
|
+
};
|
|
16
|
+
} | {
|
|
17
|
+
error: null;
|
|
18
|
+
isLoading: true;
|
|
19
|
+
isRefreshing: false;
|
|
20
|
+
values: {
|
|
21
|
+
[K in keyof T]: ReturnType<T[K]> extends AsyncState<any> ? ReturnType<T[K]>["value"] : ReturnType<T[K]>;
|
|
22
|
+
};
|
|
23
|
+
} | {
|
|
24
|
+
error: null;
|
|
25
|
+
isLoading: false;
|
|
26
|
+
isRefreshing: true;
|
|
27
|
+
values: {
|
|
28
|
+
[K in keyof T]: ReturnType<T[K]> extends AsyncState<any> ? NonNullable<ReturnType<T[K]>["value"]> : ReturnType<T[K]>;
|
|
29
|
+
};
|
|
30
|
+
} | {
|
|
31
|
+
error: null;
|
|
32
|
+
isLoading: false;
|
|
33
|
+
isRefreshing: false;
|
|
34
|
+
values: {
|
|
35
|
+
[K in keyof T]: ReturnType<T[K]> extends AsyncState<any> ? NonNullable<ReturnType<T[K]>["value"]> : ReturnType<T[K]>;
|
|
36
|
+
};
|
|
37
|
+
};
|
|
38
|
+
export declare function useSuspend<T extends Record<string, any>>(asyncs: T): SuspendState<T>;
|
|
39
|
+
export {};
|
|
40
|
+
//# sourceMappingURL=useSuspend.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useSuspend.d.ts","sourceRoot":"","sources":["../src/useSuspend.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAW,MAAM,YAAY,CAAC;AAIjD,KAAK,YAAY,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,CAAC,IACjD;IACE,KAAK,EAAE,KAAK,CAAC;IACb,SAAS,EAAE,IAAI,CAAC;IAChB,YAAY,EAAE,KAAK,CAAC;IACpB,MAAM,EAAE;SACL,CAAC,IAAI,MAAM,CAAC,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,UAAU,CAAC,GAAG,CAAC,GACpD,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,GACzB,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;KACrB,CAAC;CACH,GACD;IACE,KAAK,EAAE,KAAK,CAAC;IACb,SAAS,EAAE,KAAK,CAAC;IACjB,YAAY,EAAE,IAAI,CAAC;IACnB,MAAM,EAAE;SACL,CAAC,IAAI,MAAM,CAAC,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,UAAU,CAAC,GAAG,CAAC,GACpD,WAAW,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,GACtC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;KACrB,CAAC;CACH,GACD;IACE,KAAK,EAAE,IAAI,CAAC;IACZ,SAAS,EAAE,IAAI,CAAC;IAChB,YAAY,EAAE,KAAK,CAAC;IACpB,MAAM,EAAE;SACL,CAAC,IAAI,MAAM,CAAC,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,UAAU,CAAC,GAAG,CAAC,GACpD,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,GACzB,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;KACrB,CAAC;CACH,GACD;IACE,KAAK,EAAE,IAAI,CAAC;IACZ,SAAS,EAAE,KAAK,CAAC;IACjB,YAAY,EAAE,IAAI,CAAC;IACnB,MAAM,EAAE;SACL,CAAC,IAAI,MAAM,CAAC,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,UAAU,CAAC,GAAG,CAAC,GACpD,WAAW,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,GACtC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;KACrB,CAAC;CACH,GACD;IACE,KAAK,EAAE,IAAI,CAAC;IACZ,SAAS,EAAE,KAAK,CAAC;IACjB,YAAY,EAAE,KAAK,CAAC;IACpB,MAAM,EAAE;SACL,CAAC,IAAI,MAAM,CAAC,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,UAAU,CAAC,GAAG,CAAC,GACpD,WAAW,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,GACtC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;KACrB,CAAC;CACH,CAAC;AAEN,wBAAgB,UAAU,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,MAAM,EAAE,CAAC,mBAsDlE"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { isAsync } from "./useAsync";
|
|
2
|
+
import { useEffect } from "./useEffect";
|
|
3
|
+
import { assignState, useState } from "./useState";
|
|
4
|
+
export function useSuspend(asyncs) {
|
|
5
|
+
const state = useState({
|
|
6
|
+
isLoading: true,
|
|
7
|
+
isRefreshing: false,
|
|
8
|
+
error: null,
|
|
9
|
+
values: Object.keys(asyncs).reduce((aggr, key) => {
|
|
10
|
+
let value = asyncs[key]();
|
|
11
|
+
if (isAsync(value)) {
|
|
12
|
+
value = value.value;
|
|
13
|
+
}
|
|
14
|
+
aggr[key] = value;
|
|
15
|
+
return aggr;
|
|
16
|
+
}, {}),
|
|
17
|
+
});
|
|
18
|
+
useEffect(() => {
|
|
19
|
+
let isLoading = false;
|
|
20
|
+
let isRefreshing = false;
|
|
21
|
+
let error;
|
|
22
|
+
const values = {};
|
|
23
|
+
for (const key in asyncs) {
|
|
24
|
+
let value = asyncs[key]();
|
|
25
|
+
if (!isAsync(value)) {
|
|
26
|
+
values[key] = value;
|
|
27
|
+
continue;
|
|
28
|
+
}
|
|
29
|
+
values[key] = value.value;
|
|
30
|
+
if (value.isLoading) {
|
|
31
|
+
isLoading = true;
|
|
32
|
+
}
|
|
33
|
+
else if (value.isRefreshing) {
|
|
34
|
+
isRefreshing = true;
|
|
35
|
+
}
|
|
36
|
+
if (value.error) {
|
|
37
|
+
error = value.error;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
state.isLoading = isLoading;
|
|
41
|
+
state.isRefreshing = isLoading ? false : isRefreshing;
|
|
42
|
+
state.error = error || null;
|
|
43
|
+
if (!state.isLoading && !state.isRefreshing && !error) {
|
|
44
|
+
assignState(state.values, values);
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
return state;
|
|
48
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { AsyncState } from "./useAsync";
|
|
2
|
+
type SuspendAsyncState<T extends Record<string, AsyncState<any>>> = {
|
|
3
|
+
values: {
|
|
4
|
+
[K in keyof T]: T[K]["value"];
|
|
5
|
+
};
|
|
6
|
+
} & ({
|
|
7
|
+
isPending: true;
|
|
8
|
+
error: null;
|
|
9
|
+
} | {
|
|
10
|
+
isPending: false;
|
|
11
|
+
error: string;
|
|
12
|
+
} | {
|
|
13
|
+
isPending: false;
|
|
14
|
+
error: null;
|
|
15
|
+
});
|
|
16
|
+
export declare function useSuspendAsync<T extends Record<string, AsyncState<any>>>(asyncs: T): SuspendAsyncState<T>;
|
|
17
|
+
export {};
|
|
18
|
+
//# sourceMappingURL=useSuspendAsync.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useSuspendAsync.d.ts","sourceRoot":"","sources":["../src/useSuspendAsync.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAIxC,KAAK,iBAAiB,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,GAAG,CAAC,CAAC,IAAI;IAClE,MAAM,EAAE;SACL,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;KAC9B,CAAC;CACH,GAAG,CACA;IACE,SAAS,EAAE,IAAI,CAAC;IAChB,KAAK,EAAE,IAAI,CAAC;CACb,GACD;IACE,SAAS,EAAE,KAAK,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;CACf,GACD;IACE,SAAS,EAAE,KAAK,CAAC;IACjB,KAAK,EAAE,IAAI,CAAC;CACb,CACJ,CAAC;AAEF,wBAAgB,eAAe,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,GAAG,CAAC,CAAC,EACvE,MAAM,EAAE,CAAC,wBAyCV"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { useEffect } from "./useEffect";
|
|
2
|
+
import { useState } from "./useState";
|
|
3
|
+
export function useSuspendAsync(asyncs) {
|
|
4
|
+
const state = useState({
|
|
5
|
+
isPending: false,
|
|
6
|
+
error: null,
|
|
7
|
+
values: Object.keys(asyncs).reduce((aggr, key) => ({ ...aggr, [key]: asyncs[key].value }), {}),
|
|
8
|
+
});
|
|
9
|
+
useEffect(() => {
|
|
10
|
+
let isPending = false;
|
|
11
|
+
let error = "";
|
|
12
|
+
for (const key in asyncs) {
|
|
13
|
+
if (asyncs[key].error) {
|
|
14
|
+
error += asyncs[key].error + "\n";
|
|
15
|
+
continue;
|
|
16
|
+
}
|
|
17
|
+
if (asyncs[key].isPending) {
|
|
18
|
+
isPending = true;
|
|
19
|
+
continue;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
if (error) {
|
|
23
|
+
state.isPending = false;
|
|
24
|
+
state.error = error;
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
if (isPending) {
|
|
28
|
+
state.isPending = false;
|
|
29
|
+
state.error = null;
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
for (const key in asyncs) {
|
|
33
|
+
state.values[key] = asyncs[key].value;
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
return state;
|
|
37
|
+
}
|