Skip to content

Instantly share code, notes, and snippets.

@stevegreatrex
Created July 11, 2019 06:10
Show Gist options
  • Save stevegreatrex/581eb53920c2a42af6822f0809923f8c to your computer and use it in GitHub Desktop.
Save stevegreatrex/581eb53920c2a42af6822f0809923f8c to your computer and use it in GitHub Desktop.
Async Effect Hook
interface LoadStarted { type: 'STARTED'; }
interface LoadComplete<TResult> { type: 'COMPLETE'; result: TResult; }
interface LoadFailed { type: 'FAILED'; error: any; }
type LoadAction<TResult> = LoadStarted | LoadComplete<TResult> | LoadFailed;
type AsyncFunction<TResult> = () => Promise<TResult>;
interface State<TResult> {
isLoading: boolean;
result?: TResult;
error?: any;
}
function reducer<TResult>(state: State<TResult>, action: LoadAction<TResult>) {
switch (action.type) {
case 'STARTED':
return { ...state, isLoading: true, error: undefined };
case 'COMPLETE':
return { ...state, isLoading: false, result: action.result };
case 'FAILED':
return { ...state, isLoading: false, error: action.error };
}
}
function useAsyncEffect<TResult>(action: AsyncFunction<TResult>, dependencies: any[]) {
type ReducerType = Reducer<State<TResult>, LoadAction<TResult>>;
const [state, dispatch] = useReducer<ReducerType>(reducer, {
isLoading: false
});
useEffect(() => {
async function loadTheThings() {
dispatch({ type: 'STARTED' });
try {
const result = await action();
dispatch({ type: 'COMPLETE', result });
} catch (error) {
dispatch({ type: 'FAILED', error });
}
}
loadTheThings();
}, dependencies);
return state;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment