1 | import { useCallback, useEffect, useRef, useState } from 'react';
|
2 |
|
3 | /**
|
4 | * A hook that mirrors `useState` in function and API, expect that setState
|
5 | * calls return a promise that resolves after the state has been set (in an effect).
|
6 | *
|
7 | * This is _similar_ to the second callback in classy setState calls, but fires later.
|
8 | *
|
9 | * ```ts
|
10 | * const [counter, setState] = useStateAsync(1);
|
11 | *
|
12 | * const handleIncrement = async () => {
|
13 | * await setState(2);
|
14 | * doWorkRequiringCurrentState()
|
15 | * }
|
16 | * ```
|
17 | *
|
18 | * @param initialState initialize with some state value same as `useState`
|
19 | */
|
20 | export default function useStateAsync(initialState) {
|
21 | var _useState = useState(initialState),
|
22 | state = _useState[0],
|
23 | setState = _useState[1];
|
24 |
|
25 | var resolvers = useRef([]);
|
26 | useEffect(function () {
|
27 | resolvers.current.forEach(function (resolve) {
|
28 | return resolve(state);
|
29 | });
|
30 | resolvers.current.length = 0;
|
31 | }, [state]);
|
32 | var setStateAsync = useCallback(function (update) {
|
33 | return new Promise(function (resolve, reject) {
|
34 | setState(function (prevState) {
|
35 | try {
|
36 | var nextState; // ugly instanceof for typescript
|
37 |
|
38 | if (update instanceof Function) {
|
39 | nextState = update(prevState);
|
40 | } else {
|
41 | nextState = update;
|
42 | } // If state does not change, we must resolve the promise because
|
43 | // react won't re-render and effect will not resolve. If there are already
|
44 | // resolvers queued, then it should be safe to assume an update will happen
|
45 |
|
46 |
|
47 | if (!resolvers.current.length && Object.is(nextState, prevState)) {
|
48 | resolve(nextState);
|
49 | } else {
|
50 | resolvers.current.push(resolve);
|
51 | }
|
52 |
|
53 | return nextState;
|
54 | } catch (e) {
|
55 | reject(e);
|
56 | throw e;
|
57 | }
|
58 | });
|
59 | });
|
60 | }, [setState]);
|
61 | return [state, setStateAsync];
|
62 | } |
\ | No newline at end of file |