import { useReducer as useReactReducer , Reducer , useMemo , Dispatch , useState , useEffect , useContext , ReducerState , ReducerAction } from "react" ; import { StateInspectorContext , EnhancedStore } from "./context" ; export function useHookedReducer < S , A > ( reducer , initialState , store , reducerId ) { const initialReducerState = useMemo ( ( ) => { const initialStateInStore = store . getState ( ) [ reducerId ] ; return initialStateInStore === undefined ? initialState : initialStateInStore ; } , [ ] ) ; const [ localState , setState ] = useState < S > ( initialReducerState ) ; const dispatch = useMemo < Dispatch < A > > ( ( ) => { const dispatch = ( action ) => { if ( action && typeof action === "object" && typeof action . type === "string" ) { store . dispatch ( { type : `${ reducerId }/${ action . type }` , payload : action } ) ; } else { store . dispatch ( { type : reducerId , payload : action } ) ; } } ; return dispatch ; } , [ ] ) ; useEffect ( ( ) => { const teardown = store . registerHookedReducer ( reducer , initialReducerState , reducerId ) ; let lastReducerState = localState ; const unsubscribe = store . subscribe ( ( ) => { const storeState = store . getState ( ) ; const reducerState = storeState [ reducerId ] ; if ( lastReducerState !== reducerState ) { setState ( reducerState ) ; } lastReducerState = reducerState ; } ) ; return ( ) => { unsubscribe ( ) ; teardown ( ) ; } ; } , [ ] ) ; return [ localState , dispatch ] ; } export function useReducer < R extends Reducer < any , any > > ( reducer , initialState , id ? ) ; export function useReducer < R extends Reducer < any , any > , I > ( reducer , initialState , initializer , id ? ) ; export function useReducer < R extends Reducer < any , any > , I > ( reducer , initialState , initializer , id ? ) ; export function useReducer < R extends Reducer < any , any > , I > ( reducer , initialState , ... args ) { let id ; let initializer = args [ 0 ] ; if ( args . length === 2 ) { initializer = args [ 0 ] ; id = args [ 1 ] ; } else if ( typeof args [ 0 ] === "string" || typeof args [ 0 ] === "number" ) { id = args [ 0 ] ; } else { initializer = args [ 0 ] ; id = args [ 1 ] ; } const store = useContext ( StateInspectorContext ) ; const initializedState = initializer ? initializer ( initialState ) : initialState ; return store && id ? useHookedReducer ( reducer , initializedState , store , id ) : useReactReducer ( reducer , initialState , initializer ) ; }