From f1f8420de87ecb377a9df0a402795b5a388fd730 Mon Sep 17 00:00:00 2001 From: Madeorsk Date: Fri, 19 Jul 2024 21:48:28 +0200 Subject: [PATCH] Add Promisable type and allow it as an argument to useAsync. --- src/Async.tsx | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/src/Async.tsx b/src/Async.tsx index d7cc11a..46838f7 100644 --- a/src/Async.tsx +++ b/src/Async.tsx @@ -1,5 +1,10 @@ import React, {useEffect, useState} from "react"; +/** + * A type that can be returned by a promise or as is. + */ +export type Promisable = T|Promise; + /** * Asynchronous data state. */ @@ -12,7 +17,7 @@ interface AsyncState /** * The promise which is retrieved (or has retrieved) data. */ - promise: Promise; + promise: Promisable; /** * Error thrown by the promise. */ @@ -33,20 +38,20 @@ export type PromiseFn = () => Promise; * @param promise The promise or a function that produces a promise. * @param deps When one of the `deps` change, it will wait for the promise again. */ -export function useAsync(promise: Promise|PromiseFn, deps: any[] = []): AsyncState +export function useAsync(promise: Promisable|PromiseFn, deps: any[] = []): AsyncState { // Get the actual promise from the function if there is one. if ((promise as PromiseFn)?.call) promise = (promise as PromiseFn)(); - else + else if (promise instanceof Promise) promise = Promise.race([promise as Promise]); // The async state. const [state, setState] = useState>({ - pending: true, - promise: promise, + pending: promise instanceof Promise, + promise: promise as Promisable, error: undefined, - data: undefined, + data: promise instanceof Promise ? undefined : promise as T, }); /** @@ -60,7 +65,11 @@ export function useAsync(promise: Promise|PromiseFn, deps: any[] = []): // Reconfigure the promise when any deps have changed. useEffect(() => { - (promise as Promise).then((result) => { + if (!(promise instanceof Promise)) + // If it's not a promise, there is nothing to wait for. + return; + + promise.then((result) => { // When there is a result, disable pending state and set retrieved data, without error. updateState({ pending: false, @@ -79,7 +88,7 @@ export function useAsync(promise: Promise|PromiseFn, deps: any[] = []): // Promise is ready: reset the state to pending with the configured promise, without data and error. updateState({ pending: true, - promise: promise as Promise, + promise: promise, error: undefined, data: undefined, });