1import { createContext, useCallback, useContext } from 'react'; 2import { Action } from '@reduxjs/toolkit'; 3 4export type Reducer<S, A extends Action> = (state: S, action: A) => S; 5 6export const combineReducers = <S, A extends Action = Action>(reducers: { [P in keyof S]: Reducer<S[P], A> }) => ( 7 state: S, 8 action: A 9): Partial<S> => { 10 const newState = {} as S; 11 for (const key in reducers) { 12 newState[key] = reducers[key](state[key], action); 13 } 14 return newState; 15}; 16 17export const useStatelessReducer = <State, A = Action>( 18 onChange: (value: State) => void, 19 state: State, 20 reducer: (state: State, action: A) => State 21) => { 22 const dispatch = useCallback( 23 (action: A) => { 24 onChange(reducer(state, action)); 25 }, 26 [onChange, state, reducer] 27 ); 28 29 return dispatch; 30}; 31 32export const DispatchContext = createContext<((action: Action) => void) | undefined>(undefined); 33 34export const useDispatch = <T extends Action = Action>(): ((action: T) => void) => { 35 const dispatch = useContext(DispatchContext); 36 37 if (!dispatch) { 38 throw new Error('Use DispatchContext first.'); 39 } 40 41 return dispatch; 42}; 43