hooks
作用于函数组件, 所以我们看一下对于函数组件是怎么渲染的
- 初次渲染:
- prepareToReadContext
- 从fiber对象上获取memoizedState, 这个属性包含了所有hooks的状态,是一个链表结构;
- 获取第一个hooks对象,currentHook
- let children = Component(props) // 执行函数组件
const ref = useRef(null)
function useRef(initialValue){
// 1. 创建一个 hook 对象
const hook = {
memoizedState: null, // ref的值: {current: initialValue}
baseState: null,
baseQueue: null,
queue: null,
next: null, // 指向下一个hook
}
const ref = {current: initialValue}
// 2. 绑定到fiber对象的memoizedState上(状态,组件更新的时候也可以拿到这个状态)
currentlyRenderingFiber.memoizedState = hook
return ref;
// 3. 如果是更新阶段进来,直接返回 hook.memoizedState
}
const cb = useCallback(() => {}, [])
function useCallback(callback, deps) {
// 1. 创建 hook 对象
const hook = {
memoizedState: null, // [callback, deps]
baseState: null,
baseQueue: null,
queue: null,
next: null,
};
// 2. 更新阶段,依赖对比
const nextDeps = deps
const prevState = hook.memoizedState
const prevDeps = prevState[1]
if (prevState !== null) {
if (nextDeps !== null) {
if (areHookInputsEqual(nextDeps, prevDeps)) return prevState[0]
}
}
hook.memoizedState = [callback, deps]
return callback
}
const res = useMemo(() => 'demo', [])
和 useCallback 其实是一样的,只不过存的值是函数的返回值
const [val, setVal] = useState(null)
function useState(initialState) {
// 1. 创建 hook 对象
const hook = {
memoizedState: null,
baseState: null,
baseQueue: null,
queue: null,
next: null, // 指向下一个hook
}
if (typeof initialState === 'function') initialState = initialState()
// 2. 保存 state 的值
hook.memoizedState = hook.baseState = initialState;
// 3. 更新队列,批量更新用的
hook.queue = { /* ... */}
// 4. 往queue中塞入一个更新,通知react重新渲染
const dispatch = dispatchSetState.bind(
null,
currentlyRenderingFiber,
queue,
)
return [hook.memoizedState, dispatch]
// 因为fiber对象保存了组件状态,所以更新时就能拿到这个queue去遍历做state的更新,返回最新的hook.memoizedState
}
useEffect(() => {}, [])
function mountEffectImpl(fiberFlags, hookFlags, create, deps) {
// flag标记 useEffect 和 useLayoutEffect
const hook = mountWorkInProgressHook() // 创建 hook 对象
const nextDeps = deps
// 副作用标记
currentlyRenderingFiber.flags |= fiberFlags
// effect 对象(依赖,回调,销毁回调,next)
const effect = {
tag,
create,
destroy,
deps,
// Circular
next,
}
hook.memoizedState = pushEffect(
HookHasEffect | hookFlags,
create,
undefined,
nextDeps,
)
// 最终 effect 会形成一个环形链表,保存在fiber上,在react的生命周期执行阶段执行
}