refactor(frontend): create useAsync hook for handling API data

This commit is contained in:
Julian Tölle 2020-06-05 01:22:04 +02:00
parent 42e8b886a0
commit 6a6ba493f6
2 changed files with 49 additions and 19 deletions

View file

@ -0,0 +1,38 @@
import React, { useState, useEffect, useCallback } from "react";
type UseAsync = <T>(
asyncFunction: () => Promise<T>,
initialValue: T
) => { pending: boolean; value: T; error: Error | null };
export const useAsync: UseAsync = <T extends any>(
asyncFunction: () => Promise<T>,
initialValue: T
) => {
const [pending, setPending] = useState(false);
const [value, setValue] = useState<T>(initialValue);
const [error, setError] = useState(null);
// 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(() => {
setPending(true);
setValue(initialValue);
setError(null);
return asyncFunction()
.then((response) => setValue(response))
.catch((err) => setError(err))
.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(() => {
execute();
}, [execute]);
return { execute, pending, value, error };
};