import { update , isFn , getCurrentFiber } from "./reconcile" ; import { DependencyList , Reducer , IFiber , Dispatch , SetStateAction , EffectCallback , HookTypes , RefObject , IEffect , } from "./type" ; let cursor = 0 ; export const resetCursor = ( ) => { cursor = 0 ; } ; export const useState = < T > ( initState ) : [ T , Dispatch < SetStateAction < T > > ] => { return useReducer ( null , initState ) ; } ; export const useReducer = < S , A > ( reducer ? , initState ? ) : [ S , Dispatch < A > ] => { const [ hook , current ] = getHook < S > ( cursor ++ ) ; if ( hook . length === 0 ) { hook [ 0 ] = initState ; hook [ 1 ] = ( value ) => { hook [ 0 ] = reducer ? reducer ( hook [ 0 ] , value as any ) : isFn ( value ) ? value ( hook [ 0 ] ) : value ; update ( current ) ; } ; } return hook ; } ; export const useEffect = ( cb , deps ? ) : void => { return effectImpl ( cb , deps ! , "effect" ) ; } ; export const useLayout = ( cb , deps ? ) : void => { return effectImpl ( cb , deps ! , "layout" ) ; } ; const effectImpl = ( cb , deps , key ) : void => { const [ hook , current ] = getHook ( cursor ++ ) ; if ( isChanged ( hook [ 1 ] , deps ) ) { hook [ 0 ] = cb ; hook [ 1 ] = deps ; current . hooks [ key ] . push ( hook ) ; } } ; export const useMemo = < S = Function > ( cb , deps ? ) : S => { const hook = getHook < S > ( cursor ++ ) [ 0 ] ; if ( isChanged ( hook [ 1 ] , deps ! ) ) { hook [ 1 ] = deps ; return ( hook [ 0 ] = cb ( ) ) ; } return hook [ 0 ] ; } ; export const useCallback = < T extends ( ... args : any [ ] ) => void > ( cb , deps ? ) : T => { return useMemo ( ( ) => cb , deps ) ; } ; export const useRef = < T > ( current ) : RefObject < T > => { return useMemo ( ( ) => ( { current } ) , [ ] ) ; } ; export const getHook = < S = Function | undefined , Dependency = any > ( cursor ) : [ [ S , Dependency ] , IFiber ] => { const current = getCurrentFiber ( ) ; const hooks = current . hooks || ( current . hooks = { list : [ ] , effect : [ ] , layout : [ ] } ) ; if ( cursor >= hooks . list . length ) { hooks . list . push ( [ ] as IEffect ) ; } return [ ( hooks . list [ cursor ] as unknown ) as [ S , Dependency ] , current ] ; } ; export const isChanged = ( a , b ) => { return ! a || a . length !== b . length || b . some ( ( arg , index ) => ! Object . is ( arg , a [ index ] ) ) ; } ;