| 42 | function useAsync<T>(promiseFn: PromiseFn<T>, options?: AsyncOptions<T>): AsyncState<T> |
| 43 | |
| 44 | function useAsync<T>(arg1: AsyncOptions<T> | PromiseFn<T>, arg2?: AsyncOptions<T>): AsyncState<T> { |
| 45 | const options: AsyncOptions<T> = |
| 46 | typeof arg1 === "function" |
| 47 | ? { |
| 48 | ...arg2, |
| 49 | promiseFn: arg1, |
| 50 | } |
| 51 | : arg1 |
| 52 | |
| 53 | const counter = useRef(0) |
| 54 | const isMounted = useRef(true) |
| 55 | const lastArgs = useRef<any[] | undefined>(undefined) |
| 56 | const lastOptions = useRef<AsyncOptions<T>>(options) |
| 57 | const lastPromise = useRef<Promise<T>>(neverSettle) |
| 58 | const abortController = useRef<AbortController>(new MockAbortController()) |
| 59 | |
| 60 | const { devToolsDispatcher } = globalScope.__REACT_ASYNC__ |
| 61 | const { reducer, dispatcher = devToolsDispatcher } = options |
| 62 | const [state, _dispatch] = useReducer( |
| 63 | reducer ? (state, action) => reducer(state, action, asyncReducer) : asyncReducer, |
| 64 | options, |
| 65 | init |
| 66 | ) |
| 67 | const dispatch = useCallback( |
| 68 | dispatcher |
| 69 | ? action => dispatcher(action, dispatchMiddleware(_dispatch), lastOptions.current) |
| 70 | : dispatchMiddleware(_dispatch), |
| 71 | [dispatcher] |
| 72 | ) |
| 73 | |
| 74 | const { debugLabel } = options |
| 75 | const getMeta: <M extends Meta = Meta>(meta?: M) => M = useCallback( |
| 76 | (meta?) => |
| 77 | ({ |
| 78 | counter: counter.current, |
| 79 | promise: lastPromise.current, |
| 80 | debugLabel, |
| 81 | ...meta, |
| 82 | } as any), |
| 83 | [debugLabel] |
| 84 | ) |
| 85 | |
| 86 | const setData = useCallback( |
| 87 | (data, callback = noop) => { |
| 88 | if (isMounted.current) { |
| 89 | dispatch({ |
| 90 | type: ActionTypes.fulfill, |
| 91 | payload: data, |
| 92 | meta: getMeta(), |
| 93 | }) |
| 94 | callback() |
| 95 | } |
| 96 | return data |
| 97 | }, |
| 98 | [dispatch, getMeta] |
| 99 | ) |
| 100 | |
| 101 | const setError = useCallback( |