Add Promisable type and allow it as an argument to useAsync.
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
This commit is contained in:
parent
76182885db
commit
f1f8420de8
1 changed files with 17 additions and 8 deletions
|
@ -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,
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue