Skip to content

Instantly share code, notes, and snippets.

@js2me
Created November 19, 2021 11:05
Show Gist options
  • Save js2me/8be024018b3616eb478718df7b56d687 to your computer and use it in GitHub Desktop.
Save js2me/8be024018b3616eb478718df7b56d687 to your computer and use it in GitHub Desktop.
simple reducer for usage in React
/* eslint-disable @typescript-eslint/ban-types */
import { Reducer, useCallback, useReducer } from 'react'
import { useConstant } from 'hooks/useConstant'
const reducerCreator =
<S extends object>(filter?: (prev: S, curr: S) => boolean) =>
(state: S, update: (prevState: S) => S | void) => {
const nextState = update(state)
return nextState === void 0 || (filter && filter(state, nextState))
? state
: nextState
}
// eslint-disable-next-line @typescript-eslint/ban-types,@typescript-eslint/explicit-module-boundary-types
export const useSimpleReducer = <S extends object>({
initialState: stateInitializer,
filter,
}: {
initialState: S | (() => S)
filter?: (prev: S, curr: S) => boolean
}) => {
const { initialState, reducer } = useConstant(() => {
return {
initialState:
typeof stateInitializer === 'function'
? stateInitializer()
: stateInitializer,
reducer: reducerCreator(filter),
}
})
const [state, setState] = useReducer<Reducer<S, (prevState: S) => S | void>>(
reducer,
initialState,
)
const updateState = useCallback((update: Partial<S>) => {
setState((prev) => ({ ...prev, ...update }))
}, [])
const resetState = useCallback(() => {
setState(() => ({ ...initialState }))
}, [])
return [state, updateState, resetState] as const
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment