Skip to content

Instantly share code, notes, and snippets.

@emeraldsanto
Last active May 14, 2021 00:56
Show Gist options
  • Select an option

  • Save emeraldsanto/9020b8af3ff00bef9d0397ba3546259f to your computer and use it in GitHub Desktop.

Select an option

Save emeraldsanto/9020b8af3ff00bef9d0397ba3546259f to your computer and use it in GitHub Desktop.
Small `useReducer` example
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