Skip to content

Instantly share code, notes, and snippets.

@luiznasciment0
Last active May 7, 2023 13:24
Show Gist options
  • Save luiznasciment0/7d5bb723e178082d3333c1b09e6e2879 to your computer and use it in GitHub Desktop.
Save luiznasciment0/7d5bb723e178082d3333c1b09e6e2879 to your computer and use it in GitHub Desktop.
import React from "react";
type Status = "idle" | "pending" | "resolved" | "rejected";
interface RequestState<DataType> {
data: DataType | null;
status: Status;
error: unknown;
}
interface Pending {
type: "pending";
}
interface Resolved<DataType> {
type: "resolved";
payload: { data: DataType };
}
interface Rejected {
type: "rejected";
payload: { error: unknown };
}
type Actions<DataType> = Pending | Resolved<DataType> | Rejected;
type Reducer<DataType> = (_: RequestState<DataType>, action: Actions<DataType>) => RequestState<DataType>
function reducer<DataType>(
_: RequestState<DataType>,
action: Actions<DataType>
): RequestState<DataType> {
switch (action.type) {
case "pending": {
return { status: "pending", data: null, error: null };
}
case "resolved": {
return { status: "resolved", data: action.payload.data, error: null };
}
case "rejected": {
return { status: "rejected", data: null, error: action.payload.error };
}
default: {
throw new Error(`Unhandled action type`);
}
}
}
function useRequest<DataType>(
initialState: Partial<RequestState<DataType>> = {}
): {
data: DataType | null;
error: unknown;
status: Status;
runRequest: (requestPromise: Promise<DataType>) => Promise<void>;
} {
const [state, dispatch] = React.useReducer<Reducer<DataType>>(reducer, {
status: "idle",
data: null,
error: null,
...initialState,
});
const { data, error, status } = state;
const runRequest = React.useCallback(
async (requestPromise: Promise<DataType>) => {
dispatch({ type: "pending" });
try {
const response = await requestPromise;
dispatch({ type: "resolved", payload: { data: response } });
} catch (error) {
dispatch({ type: "rejected", payload: { error } });
}
},
[dispatch]
);
return {
data,
error,
status,
runRequest,
};
}
export default useRequest;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment