use-middleware-reducer
Version:
An efficient react hook to benefit from the huge middleware ecosystem of redux
49 lines (37 loc) • 1.32 kB
text/typescript
import * as React from 'react'
export type Dispatch = (action: any) => any
export type MiddlewareAPI<A> = { getState: () => A; dispatch: Dispatch }
export type Middleware<A> = (
api: MiddlewareAPI<A>
) => (next: Dispatch) => Dispatch
export const useMiddlewareReducer = <A, B>(
reducer: (state: A, action: B) => A,
initialState: A,
middlewares: Middleware<A>[] = []
): [A, Dispatch] => {
const [state, setState] = React.useState(initialState)
const stateRef = React.useRef(state)
const dispatch = React.useMemo(() => {
let dispatch: Dispatch = () => {
throw new Error(
`Dispatching while constructing your middleware is not allowed. ` +
`Other middleware would not be applied to this dispatch.`
)
}
const middlewareAPI = {
getState: () => stateRef.current,
dispatch: action => dispatch(action)
}
const localDispatch = action => {
stateRef.current = reducer(stateRef.current, action)
setState(stateRef.current)
}
dispatch = middlewares
.map(middleware => middleware(middlewareAPI))
.reduceRight((acc, middleware) => middleware(acc), localDispatch)
return dispatch
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [])
return [state, dispatch]
}
export default useMiddlewareReducer