mirror of
https://github.com/apricote/Listory.git
synced 2026-01-13 21:21:02 +00:00
refactor(frontend): create useAsync hook for handling API data
This commit is contained in:
parent
42e8b886a0
commit
6a6ba493f6
2 changed files with 49 additions and 19 deletions
38
frontend/src/hooks/use-async.tsx
Normal file
38
frontend/src/hooks/use-async.tsx
Normal 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 };
|
||||
};
|
||||
Loading…
Add table
Add a link
Reference in a new issue