Created
May 9, 2022 00:58
-
-
Save mauroc8/cbb4162babd73f81f2b92464327d5960 to your computer and use it in GitHub Desktop.
React hooks
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, 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