Skip to content

Instantly share code, notes, and snippets.

@anthowen
Last active November 29, 2022 09:34
Show Gist options
  • Save anthowen/7309f9d54dcdeefcefab1e37a75d716c to your computer and use it in GitHub Desktop.
Save anthowen/7309f9d54dcdeefcefab1e37a75d716c to your computer and use it in GitHub Desktop.
A react custom hook designed for querying data from API. (TypeScript)
import { useState, useReducer, useEffect } from 'react';
import { Nullable } from 'interfaces';
type SearchState<T> = {
results: Array<T>;
isSearching: boolean;
isError: boolean;
};
type SearchAction<T> =
| { type: 'FETCH_INIT' }
| { type: 'FETCH_SUCCESS'; payload: Array<T> }
| { type: 'FETCH_FAILURE' };
const createDataFetchReducer = <T>() => (
state: SearchState<T>,
action: SearchAction<T>,
): SearchState<T> => {
switch (action.type) {
case 'FETCH_INIT':
return {
...state,
isSearching: true,
isError: false,
};
case 'FETCH_SUCCESS':
return {
...state,
isSearching: false,
isError: false,
results: action.payload,
};
case 'FETCH_FAILURE':
return {
...state,
isSearching: false,
isError: true,
};
default:
throw new Error();
}
};
export type FilterAPI = (param?: Nullable<string>) => Promise<any>;
export default function useFilter<T>(
apiAction: FilterAPI,
initialParam: Nullable<string> | undefined,
initialData: Array<T>,
) {
const [param, setParam] = useState(initialParam);
const dataFetchReducer = createDataFetchReducer<T>();
const [state, dispatch] = useReducer(dataFetchReducer, {
isSearching: false,
isError: false,
results: initialData,
});
useEffect(() => {
let didCancel = false;
const fetchData = async () => {
dispatch({ type: 'FETCH_INIT' });
try {
const data = await apiAction(param);
if (!didCancel) {
dispatch({ type: 'FETCH_SUCCESS', payload: data });
}
} catch (error) {
if (!didCancel) {
dispatch({ type: 'FETCH_FAILURE' });
}
}
};
if (typeof param !== 'undefined' && param !== null) fetchData();
return () => {
didCancel = true;
};
}, [param, apiAction]);
return [state, setParam] as const;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment