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";
|
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.
|
* Asynchronous data state.
|
||||||
*/
|
*/
|
||||||
|
@ -12,7 +17,7 @@ interface AsyncState<T>
|
||||||
/**
|
/**
|
||||||
* The promise which is retrieved (or has retrieved) data.
|
* The promise which is retrieved (or has retrieved) data.
|
||||||
*/
|
*/
|
||||||
promise: Promise<T>;
|
promise: Promisable<T>;
|
||||||
/**
|
/**
|
||||||
* Error thrown by the promise.
|
* 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 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.
|
* @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.
|
// Get the actual promise from the function if there is one.
|
||||||
if ((promise as PromiseFn<T>)?.call)
|
if ((promise as PromiseFn<T>)?.call)
|
||||||
promise = (promise as PromiseFn<T>)();
|
promise = (promise as PromiseFn<T>)();
|
||||||
else
|
else if (promise instanceof Promise)
|
||||||
promise = Promise.race([promise as Promise<T>]);
|
promise = Promise.race([promise as Promise<T>]);
|
||||||
|
|
||||||
// The async state.
|
// The async state.
|
||||||
const [state, setState] = useState<AsyncState<T>>({
|
const [state, setState] = useState<AsyncState<T>>({
|
||||||
pending: true,
|
pending: promise instanceof Promise,
|
||||||
promise: promise,
|
promise: promise as Promisable<T>,
|
||||||
error: undefined,
|
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.
|
// Reconfigure the promise when any deps have changed.
|
||||||
useEffect(() => {
|
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.
|
// When there is a result, disable pending state and set retrieved data, without error.
|
||||||
updateState({
|
updateState({
|
||||||
pending: false,
|
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.
|
// Promise is ready: reset the state to pending with the configured promise, without data and error.
|
||||||
updateState({
|
updateState({
|
||||||
pending: true,
|
pending: true,
|
||||||
promise: promise as Promise<T>,
|
promise: promise,
|
||||||
error: undefined,
|
error: undefined,
|
||||||
data: undefined,
|
data: undefined,
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in a new issue