Skip to content

Instantly share code, notes, and snippets.

@mauroc8
Created May 9, 2022 00:58
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mauroc8/cbb4162babd73f81f2b92464327d5960 to your computer and use it in GitHub Desktop.
Save mauroc8/cbb4162babd73f81f2b92464327d5960 to your computer and use it in GitHub Desktop.
React hooks
import { useReducer, useEffect, useRef, useCallback } from 'react';
/** An alternative way to write component's stateful logic. In particular, you can write
* any component without using the infamous `useEffect` hook.
*/
export function useReducerWithManagedEffects<
State extends { effects: Effect[] },
Action,
Effect
>(
config: {
initialState: () => State,
reducer: (state: State, action: Action) => State,
manageEffect: (effect: Effect, dispatch: (action: Action) => void) => void,
render: (state: State, dispatch: (action: Action) => void) => JSX.Element
}
): JSX.Element {
const { initialState, reducer, render } = config;
const [ state, dispatch ] = useReducer(reducer, null, initialState);
const { effects } = state;
const manageEffect = useCallbackRef(config.manageEffect);
useEffect(
() => {
effects.forEach(e => manageEffect(e, dispatch));
},
[ effects, manageEffect ]
);
return render(state, dispatch);
}
/** Returns a function whose implementation might change after each re-render,
* but with a stable reference across all re-renders.
*/
export function useCallbackRef<Args extends Array<unknown>, Return>(
fn: (...args: Args) => Return
): (...args: Args) => Return {
const ref = useRef(fn);
ref.current = fn;
return useCallback((...args: Args) => ref.current(...args), []);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment