Skip to content

Instantly share code, notes, and snippets.

@spjpgrd
Last active January 14, 2020 21:35
Show Gist options
  • Save spjpgrd/eb0902c0566b5a0f91fe67e9bd529975 to your computer and use it in GitHub Desktop.
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/
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