Add Promisable type and allow it as an argument to useAsync.
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful

This commit is contained in:
Madeorsk 2024-07-19 21:48:28 +02:00
parent 76182885db
commit f1f8420de8
Signed by: Madeorsk
SSH key fingerprint: SHA256:J9G0ofIOLKf7kyS2IfrMqtMaPdfsk1W02+oGueZzDDU

View file

@ -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> = T|Promise<T>;
/**
* Asynchronous data state.
*/
@ -12,7 +17,7 @@ interface AsyncState<T>
/**
* The promise which is retrieved (or has retrieved) data.
*/
promise: Promise<T>;
promise: Promisable<T>;
/**
* Error thrown by the promise.
*/
@ -33,20 +38,20 @@ export type PromiseFn<T> = () => Promise<T>;
* @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<T>(promise: Promise<T>|PromiseFn<T>, deps: any[] = []): AsyncState<T>
export function useAsync<T>(promise: Promisable<T>|PromiseFn<T>, deps: any[] = []): AsyncState<T>
{
// Get the actual promise from the function if there is one.
if ((promise as PromiseFn<T>)?.call)
promise = (promise as PromiseFn<T>)();
else
else if (promise instanceof Promise)
promise = Promise.race([promise as Promise<T>]);
// The async state.
const [state, setState] = useState<AsyncState<T>>({
pending: true,
promise: promise,
pending: promise instanceof Promise,
promise: promise as Promisable<T>,
error: undefined,
data: undefined,
data: promise instanceof Promise ? undefined : promise as T,
});
/**
@ -60,7 +65,11 @@ export function useAsync<T>(promise: Promise<T>|PromiseFn<T>, deps: any[] = []):
// Reconfigure the promise when any deps have changed.
useEffect(() => {
(promise as Promise<T>).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<T>(promise: Promise<T>|PromiseFn<T>, 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<T>,
promise: promise,
error: undefined,
data: undefined,
});