import { useState } from "react"; /** * A hook that returns a promise and its state. * * @param factory A function that returns a promise. * @returns An object containing the promise's state and result. * @example * const { loading, result, error } = usePromise(() => fetch('https://example.com') * .then(response => response.text()) * ); * if (loading) { * return

Loading...

; * } * if (error) { * return

Error: {error.message}

; * } * return

Result: {result}

; */ export function usePromise(factory: () => Promise) { const init = () => { const promise = factory(); if (!promise || typeof promise.then !== "function") { throw new Error("The factory function must return a promise."); } return promise .then(r => { setResult(r); setLoading(false); return r; }) .catch(e => { setError(e); setLoading(false); throw e; }); } const [loading, setLoading] = useState(true); const [result, setResult] = useState(undefined); const [error, setError] = useState(undefined); const [promise, setPromise] = useState(init); const retry = () => { setLoading(true); setResult(undefined); setError(undefined); setPromise(init); } return { loading, result, error, promise, retry }; } /** * A hook that returns a promise and its state. */ export function usePromiseLazy(factory: (...args: Args) => Promise) { const init = (promise: Promise) => { if (!promise || typeof promise.then !== "function") { throw new Error("The factory function must return a promise."); } return promise .then(r => { setResult(r); setLoading(false); return r; }) .catch(e => { setError(e); setLoading(false); throw e; }); } const [loading, setLoading] = useState(false); const [result, setResult] = useState(undefined); const [error, setError] = useState(undefined); const [promise, setPromise] = useState | undefined>(undefined); const execute = (...args: Args) => { setLoading(true); setResult(undefined); setError(undefined); setPromise(init(factory(...args))); } return [execute, { loading, result, error, promise }] as const; }