Created
February 21, 2026 22:53
-
-
Save web-crab/f06231867c1589a12201bd0af4ac3c56 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import { useState, useRef, useCallback } from 'react'; | |
| function parseError(error: unknown): Error { | |
| if (error instanceof Error) return error; | |
| if (typeof error === 'string') return new Error(error); | |
| return new Error('Unknown error'); | |
| } | |
| export function useAsync<Data, Args extends unknown[]>( | |
| fn: (...params: Args) => Promise<Data>, | |
| ) { | |
| const [state, setState] = useState<{ | |
| data: Data | undefined; | |
| error: Error | undefined; | |
| isLoading: boolean; | |
| }>({ | |
| data: undefined, | |
| error: undefined, | |
| isLoading: false, | |
| }); | |
| const fnRef = useRef(fn); | |
| const promiseRef = useRef<Promise<Data>>(); | |
| fnRef.current = fn; | |
| const execute = useCallback((...args: Args) => { | |
| const promise = fnRef.current(...args); | |
| promiseRef.current = promise; | |
| setState((prev) => ({ ...prev, isLoading: true })); | |
| promise | |
| .then((data) => { | |
| if (promise === promiseRef.current) { | |
| setState({ data, error: undefined, isLoading: false }); | |
| } | |
| }) | |
| .catch((error) => { | |
| if (promise === promiseRef.current) { | |
| setState({ | |
| data: undefined, | |
| error: parseError(error), | |
| isLoading: false, | |
| }); | |
| } | |
| }); | |
| }, []); | |
| return [state.data, state.isLoading, state.error, execute] as const; | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment