Last active
May 14, 2021 00:56
-
-
Save emeraldsanto/9020b8af3ff00bef9d0397ba3546259f to your computer and use it in GitHub Desktop.
Small `useReducer` example
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import { useReducer } from 'react'; | |
| /** | |
| * There are much better ways to type this | |
| * but this is not the focus of this gist. | |
| */ | |
| interface HTTPState<T> { | |
| status: 'loading' | 'error' | 'success' | |
| error?: string | |
| data?: T | |
| } | |
| /** | |
| * We define each possible action that | |
| * can be performed on our state. | |
| */ | |
| type HTTPAction<T> = { | |
| type: 'loading' | |
| } | { | |
| type: 'error' | |
| payload: string | |
| } | { | |
| type: 'success' | |
| payload: T | |
| } | |
| /** | |
| * This is where it starts to get interesting, | |
| * the consumer is able to simply dispatch an action | |
| * and the reducer handles all the logic (preferably without side-effects) | |
| * and returns the newly computed state! | |
| * | |
| * This decouples the state logic from the component, making the reducer usable elsewhere. | |
| */ | |
| function httpReducer<T>(state: HTTPState<T>, action: HTTPAction<T>): HTTPState<T> { | |
| switch (action.type) { | |
| case 'loading': | |
| return { | |
| ...state, | |
| error: undefined, | |
| status: 'loading' | |
| }; | |
| case 'error': | |
| return { | |
| ...state, | |
| status: 'error', | |
| error: action.payload | |
| } | |
| case 'success': | |
| return { | |
| ...state, | |
| status: 'success', | |
| error: undefined, | |
| data: action.payload | |
| } | |
| default: | |
| return { ...state } | |
| } | |
| } | |
| function SomeComponent() { | |
| // You need to pass an initial state to the reducer, could be defined outside the component. | |
| const [state, dispatch] = useReducer(httpReducer, { status: 'loading' }); | |
| function onError(message: string) { | |
| dispatch({ type: 'error', payload: message }); | |
| } | |
| function onSuccess(response: SomeRandomType) { | |
| dispatch({ type: 'success', payload: response }); | |
| } | |
| return ( | |
| // ... | |
| ); | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment