Skip to content

Instantly share code, notes, and snippets.

@dgca
Last active August 12, 2022 19:17
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dgca/b5e0578dbd2694363885cf7d22bf6270 to your computer and use it in GitHub Desktop.
Save dgca/b5e0578dbd2694363885cf7d22bf6270 to your computer and use it in GitHub Desktop.
Abstraction over `useReducer` to make writing reducer functions easier and without switch statements.
/**
* Abstraction over `useReducer` to make writing reducer functions easier and without
* switch statements.
*
* @see https://codesandbox.io/s/usedispatchmethods-wwkcw?file=/src/App.js
* @example
*
* const Thinger = () => {
* const [state, dispatch] = useDispatchMethods(
* {
* increment: ({ state }) => state + 1,
* decrement: ({ state }) => state - 1,
* setValue: ({ payload }) => payload
* },
* 0
* );
*
* return (
* <div>
* <p>The count is {state}</p>
* <button onClick={dispatch.increment}>Increment</button>
* <button onClick={dispatch.decrement}>Decrement</button>
* <input
* type="number"
* value={state}
* onChange={e => {
* const num = parseInt(e.target.value, 10);
* dispatch.setValue(num);
* }}
* />
* </div>
* );
* };
*/
import { useReducer, useMemo, useCallback } from "react";
export function useDispatchMethods(
methods,
initialState,
init,
dependencyArray = []
) {
const reducer = useCallback((state, { type, payload }) => {
return methods[type]({ state, payload });
}, dependencyArray);
const [state, dispatch] = useReducer(reducer, initialState, init);
const builtDispatch = useMemo(
() =>
Object.keys(methods).reduce((acc, type) => {
acc[type] = (payload) => {
dispatch({
type,
payload,
});
};
return acc;
}, {}),
dependencyArray
);
return [state, builtDispatch];
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment