1 import { useRef, useState } from 'react';
3 import useIsMounted from '@proton/hooks/useIsMounted';
4 import noop from '@proton/utils/noop';
6 export type PromiseHandlers<P> = {
8 resolver: (payload: P) => void;
9 rejecter: (error: any) => void;
14 const initializingValue = {
15 promise: Promise.resolve(),
20 } as PromiseHandlers<any>;
23 * Instrument a promise to allow a component to start, resolve or reject it as will.
24 * Support to be used even after component unmounting.
25 * Internally use a ref for storing data but use a fake state to trigger updates.
27 export const usePromise = <P>() => {
28 const isMounted = useIsMounted();
29 const [, setFakeState] = useState({});
30 const promiseRef = useRef<PromiseHandlers<P>>(initializingValue);
33 let resolver: (payload: P) => void = noop;
34 let rejecter: (error: any) => void = noop;
35 const promise = new Promise<P>((resolve, reject) => {
36 resolver = (payload) => {
38 promiseRef.current.isPending = false;
43 rejecter = (error) => {
45 promiseRef.current.isPending = false;
51 Object.assign(promiseRef.current, { promise, resolver, rejecter, renew, isPending: true });
58 if (promiseRef.current === initializingValue) {
59 promiseRef.current = { ...initializingValue, renew };
62 return promiseRef.current as PromiseHandlers<P>;