hook就是解决函数组件没有state,生命周期,逻辑不能复用的一种解决方案
dispatcher
在真实hook中,组件mount时的hook和update时的hook来源于不同对象,这类对象在源码中称为dispatcher
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 const HooksDispatcherOnMount: Dispatcher = { useCallback : mountCallback, useContext : readContext, useEffect : mountEffect, useImperativeHandle : mountImperativeHandle, useLayoutEffect : mountLayoutEffect, useMemo : mountMemo, useReducer : mountReducer, useRef : mountRef, useState : mountState, }; const HooksDispatcherOnUpdate: Dispatcher = { useCallback : updateCallback, useContext : readContext, useEffect : updateEffect, useImperativeHandle : updateImperativeHandle, useLayoutEffect : updateLayoutEffect, useMemo : updateMemo, useReducer : updateReducer, useRef : updateRef, useState : updateState, };
可见,mount时调用的hook和update时调用的hook是两个不同的函数,在FunctionComponent render前,会根据FunctionComponent对应fiber的一下条件区分mount和update
1 current === null || current.memoizedState === null
并把不同情况对应的dispatcher赋值给全局变量ReactCurrentDispatcher的current属性
1 2 ReactCurrentDispatcher.current = current === null || current.memoizedState === null ? HookDispatcherOnMount : HooksDispatcherOnUpdate
在FuntionComponent render时,会从ReactCurrentDispatcher.current(即当前dispatcher,则FunctionComponent render时调用的hook是不同函数)
Hook数据结构:
1 2 3 4 5 6 7 const hook: Hook = { memoizedState : null , baseState : null , baseQueue : null , queue : null , next : null }
memoizedState:
hook与FunctionComponent fiber都存在memoizedState属性:
fiber.memoizedState:FunctionComponent对应fiber保存的Hooks链表
hook.memoizedState:Hooks链表中保存的单一hook对应的数据
不同类型hook的memoizedState保存不同类型数据:
useState:对于const [state,updateState] = useState(initialState),memoizedState保存state的值
useReducer:对于const[state,dispatch]=useReducer(reducer,[]),memoizedState保存state的值
useEffect:memoizedState保存包含useEffect回调函数,依赖项等的链表数据结构effect,effect会保存在fiber.updateQueue
useRef:对于useRef(1),memoizedState保存{current:1}
useMemo:对于useMemo(callback,[depA]),memoizedState保存[callback,depA],与useMemo的区别是,useCallback保存的是callback函数本身,而useMemo保存的是callback函数的执行结果
有些hook没有memoizedState:
如useContext