useFetch
Introduction
This hook is created to retrieve data from the server. It uses the
Fetch Dispatcher
to handle requests and the
Cache
to manage the overall state of the data.
A prepared Command is the minimum requirement for useFetch.
If you intend to mutate
data stored on the server, we recommend choosing the
useSubmit
hook.
Initialization
const { data, error, loading, onSuccess, onError, onFinished } = useFetch(getUsers);
How it works?
useFetch
executes a command when a component is mounted or when its dependencies array changes. It uses dependency
tracking to limit re-rendering and help with performance.
Under the hood, communication with the core systems is established by event emitters. There are many "helper hooks"
that get returned from the hook, like onSuccess
, onError
, and onFinished
(among others). They will help you handle
various events in the request flow and lifecycle.
We used this approach to avoid overloading the base hook with callback logic, which causes low code readability and increases complexity.
import { useFetch } from "@hyper-fetch/react";
import { getUsers } from "server";
const UsersListPage: React.FC = () => {
const { data, error, loading, onSuccess, onError, onFinished } = useFetch(getUsers);
onSuccess(({ response }) => {
console.log(response); // [ User, User, User ]
});
onError(({ response }) => {
console.log(response); // { message: string }
});
onFinished(({ response }) => {
const [payload, error, status] = response;
console.log(payload); // [ User, User, User ] | null
console.log(error); // { message: string } | null
console.log(status); // 200 / 400 / 404 / 500 ...
});
return (
<div>
{loading && <Loader>}
{!loading && error && <Alert severity="error">{error.error_message}</Alert>}
{!loading && !error && !data.length && <div>List is empty</div>}
{!loading && !error && data.length && <div>{data.map(user => <div>{user.name}</div>)}</div>}
</div>
);
};
Options
Configuration options for useFetch
must be provided as the second parameter.
const { ... } = useFetch(command, options)
{
bounce: boolean;
bounceTime: number;
bounceType: debounce | throttle;
deepCompare: boolean | typeof isEqual;
dependencies: any[];
dependencyTracking: boolean;
disabled: boolean;
initialData: ClientResponseType<Response, Error> | null;
refresh: boolean;
refreshBlurred: boolean;
refreshOnBlur: boolean;
refreshOnFocus: boolean;
refreshOnReconnect: boolean;
refreshTime: number;
revalidateOnMount: boolean;
}
Returns
Returned values from this hook.
const values = useFetch(command);
{
data: null | T extends Command<infer D, any, any, any, any, any, any, any, any, any, any> ? D : never;
error: null | T extends Command<any, any, any, infer G, infer L, any, any, any, any, any, any> ? G | L : never;
loading: boolean;
retries: number;
status: null | number;
timestamp: null | Date;
setData: (data: ExtractResponse<T>, emitToCache?: boolean) => void;
setError: (error: ExtractError<T>, emitToCache?: boolean) => void;
setLoading: (loading: boolean, emitToHooks?: boolean) => void;
setRetries: (retries: number, emitToCache?: boolean) => void;
setStatus: (status: number | null, emitToCache?: boolean) => void;
setTimestamp: (timestamp: Date, emitToCache?: boolean) => void;
abort: () => void;
onAbort: (callback: OnErrorCallbackType<T>) => void;
onDownloadProgress: (callback: OnProgressCallbackType) => void;
onError: (callback: OnErrorCallbackType<T>) => void;
onFinished: (callback: OnFinishedCallbackType<T>) => void;
onOfflineError: (callback: OnErrorCallbackType<T>) => void;
onRequestStart: (callback: OnStartCallbackType<T>) => void;
onResponseStart: (callback: OnStartCallbackType<T>) => void;
onSuccess: (callback: OnSuccessCallbackType<T>) => void;
onUploadProgress: (callback: OnProgressCallbackType) => void;
bounce: {
active: boolean;
reset: () => void;
};
revalidate: (invalidateKey?: InvalidationKeyType | InvalidationKeyType[]) => void;
}