Last active
January 14, 2020 21:35
-
-
Save spjpgrd/eb0902c0566b5a0f91fe67e9bd529975 to your computer and use it in GitHub Desktop.
Slightly modified React Hook recipe of useAsync — Also TypeScript-ized: https://usehooks.com/useAsync/
This file contains 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, useCallback, useEffect } from "react"; | |
/** | |
* Takes an async function as an input and returns the pending, value, | |
* and error values we need to properly update our UI. | |
* | |
* Allows both immediate execution and delayed execution using the | |
* returned execute function. | |
* | |
* @param asyncFunction | |
* @param immediate Defaults to true. Set to false if you need to wait for something, | |
* like a user interaction | |
* | |
* @type Generic type defaults to any, but define it to have a type safe return value | |
* | |
* @see https://usehooks.com/useAsync/ | |
*/ | |
export const useAsync = <T = any>(asyncFunction: any, immediate = true) => { | |
const [pending, setPending] = useState(false); | |
const [value, setValue] = useState<T | null>(null); | |
const [error, setError] = useState(null); | |
const [loadCount, setLoadCount] = useState<number>(0); | |
const [errorCount, setErrorCount] = useState<number>(0); | |
/** | |
* The execute function wraps `asyncFunction` and handles setting state | |
* for pending, value, and error. | |
* | |
* `useCallback` ensures the below `useEffect` is not called on every | |
* render, but only if `asyncFunction` changes. | |
*/ | |
const execute = useCallback(async () => { | |
try { | |
setPending(true); | |
setValue(null); | |
setError(null); | |
setLoadCount(loadCount + 1); | |
const response: T | null = await asyncFunction(); | |
setValue(response); | |
} catch (error) { | |
setError(error); | |
setErrorCount(errorCount + 1); | |
} finally { | |
setPending(false); | |
} | |
}, [asyncFunction]); | |
/** | |
* Call `execute` if we want to fire it right away. | |
* | |
* Otherwise `execute` can be called later, such as in an `onClick` handler. | |
*/ | |
useEffect(() => { | |
if (immediate) { | |
execute(); | |
} | |
}, [execute, immediate]); | |
return { execute, pending, value, error, loadCount, errorCount }; | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment