Skip to content

Instantly share code, notes, and snippets.

@aishwarya257
Created August 15, 2021 10:04
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save aishwarya257/6b9b0e0c0e80e075c37e2a5a88b3232f to your computer and use it in GitHub Desktop.
Save aishwarya257/6b9b0e0c0e80e075c37e2a5a88b3232f to your computer and use it in GitHub Desktop.
Safe dispatch of useFetch function
export const FETCH_STATUS = {
pending: "pending",
resolved: "resolved",
idle: "idle",
rejected: "rejected"
} as const;
export type FetchStatus = typeof FETCH_STATUS[keyof typeof FETCH_STATUS];
type ResolvedFetch = typeof FETCH_STATUS.resolved;
export type FetchAction<T> =
| {
type: Exclude<FetchStatus, ResolvedFetch>
}
| { type: ResolvedFetch; data: T }
export type FetchState<T> =
| {
status: Exclude<FetchStatus, ResolvedFetch>
data: null;
}
| {
status: ResolvedFetch;
data: T;
}
export function fetchReducer<T>(
state: FetchState<T>,
action: FetchAction<T>
): FetchState<T> {
switch (action.type) {
case FETCH_STATUS.pending:
return { status: FETCH_STATUS.pending, data: null };
case FETCH_STATUS.resolved:
return { status: FETCH_STATUS.resolved, data: action.data };
default:
return state;
}
}
function useFetch<T = unknown>(initialData: Record<string, unknown> = {}) {
const [state, unsafeDispatch] = useReducer<
Reducer<FetchState<T>, FetchAction<T>>
>(fetchReducer, {
status: FETCH_STATUS.idle,
data: null,
...initialData
});
const dispatch = useSafeDispatch<FetchAction<T>>(unsafeDispatch);
const call = useCallback(
(url) => {
dispatch({ type: FETCH_STATUS.pending });
fetch(url).then(
(response: Response) => response.json().then((data: T) => {
dispatch({ type: FETCH_STATUS.resolved, data});
}),
);
},
[dispatch]
);
return [state, call] as const;
}
export default useFetch;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment