react-use/src/createReducer.ts
Andrew Bazhanov 9780545d6e fix: createReducer stable dispatch function identity
stable dispatch function identity so it won’t change on re-renders
2019-07-16 18:40:08 +10:00

53 lines
1.3 KiB
TypeScript

import { useCallback, useRef, useState } from 'react';
import useUpdateEffect from './useUpdateEffect';
function composeMiddleware(chain) {
return (context, dispatch) => {
return chain.reduceRight((res, middleware) => {
return middleware(context)(res);
}, dispatch);
};
}
const createReducer = (...middlewares) => {
const composedMiddleware = composeMiddleware(middlewares);
return (reducer, initialState, initializer = value => value) => {
const ref = useRef(initializer(initialState));
const [, setState] = useState(ref.current);
const dispatch = useCallback(
action => {
ref.current = reducer(ref.current, action);
setState(ref.current);
return action;
},
[reducer]
);
const dispatchRef = useRef(
composedMiddleware(
{
getState: () => ref.current,
dispatch: (...args) => dispatchRef.current(...args),
},
dispatch
)
);
useUpdateEffect(() => {
dispatchRef.current = composedMiddleware(
{
getState: () => ref.current,
dispatch: (...args) => dispatchRef.current(...args),
},
dispatch
);
}, [dispatch]);
return [ref.current, dispatchRef.current];
};
};
export default createReducer;