import * as React from 'react' ; import { Context , ContextSelector , ContextValue } from './types' ; import { useIsomorphicLayoutEffect } from './utils' ; type UseSelectorRef < Value , SelectedValue > = { selector : ContextSelector < Value , SelectedValue > ; selected : SelectedValue ; value : Value ; } ; /**
 * This hook returns context selected value by selector.
 * It will only accept context created by `createContext`.
 * It will trigger re-render if only the selected value is referencially changed.
 */ const useContextSelector = < Value , SelectedValue > ( context , selector ) : SelectedValue => { const { subscribe , value } = React . useContext ( ( context as unknown ) as Context < ContextValue < Value > > ) ; const [ , forceUpdate ] = React . useReducer ( ( c ) => c + 1 , 0 ) as [ never , ( ) => void ] ; const ref = React . useRef < UseSelectorRef < Value , SelectedValue > > ( ) ; const selected = selector ( value ) ; useIsomorphicLayoutEffect ( ( ) => { ref . current = { selector , value , selected , } ; } ) ; useIsomorphicLayoutEffect ( ( ) => { const callback = ( nextState ) => { try { const reference = ref . current as NonNullable < UseSelectorRef < Value , SelectedValue > > ; if ( reference . value === nextState || Object . is ( reference . selected , reference . selector ( nextState ) ) ) { return ; } } catch ( e ) { } forceUpdate ( ) ; } ; return subscribe ( callback ) ; } , [ subscribe ] ) ; return selected ; } ; export default useContextSelector ;