Skip to content

Instantly share code, notes, and snippets.

@ikibalnyi
Last active August 28, 2019 14:05
Show Gist options
  • Save ikibalnyi/34af0973d78c5c80fc6261eabc148a7e to your computer and use it in GitHub Desktop.
Save ikibalnyi/34af0973d78c5c80fc6261eabc148a7e to your computer and use it in GitHub Desktop.
import React, { Reducer, useEffect, useReducer } from 'react';
import { createAsyncAction } from 'typesafe-actions';
import { ResponseError } from 'utils/api/request';
const initialState = {
isLoading: false,
data: null,
error: null,
};
const REQUEST = 'REQUEST';
const SUCCESS = 'SUCCESS';
const FAILURE = 'FAILURE';
const reducer = (state, action) => {
switch (action.type) {
case REQUEST:
return { ...state, isLoading: true };
case SUCCESS:
return { ...initialState, data: action.payload };
case FAILURE:
return { ...state, isLoading: false, error: action.payload };
default:
return state;
}
};
interface State<S, E extends Error> {
isLoading: boolean;
error: E;
data: S;
}
type FetchReducer<S, E extends Error> = Reducer<State<S, E>, any>;
const fetchActions = createAsyncAction(
REQUEST,
SUCCESS,
FAILURE,
)<void, object, ResponseError>();
type UseFetchResult<S, E extends Error> = [State<S, E>, (args: any) => Promise<S>];
function useFetch<S = any, E extends Error = ResponseError>(fetchData, args?): UseFetchResult<S, E> {
const [state, dispatch] = useReducer<FetchReducer<S, E>>(reducer, initialState);
const fetchAction = (args) => {
dispatch(fetchActions.request());
return fetchData(args)
.then(data => dispatch(fetchActions.success(data)))
.catch(error => dispatch(fetchActions.failure(error)));
};
useEffect(() => {
fetchAction(args);
}, []);
return [state, fetchAction];
}
export default useFetch;
import useFetch from './useFetch';
interface User {
id: number;
name: string;
}
const fetchUser = () => fetch('/api/me')
const MyComponent = ({ isLoading, user, error }) => {
const [{ isLoading, data, error }, refetch] = useFetch<User>(fetchUser);
if (isLoading) return 'I\'m loading...';
if (error) return 'Something went wrong :(';
return (
<div>
{user.id}
</div>
);
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment