useEffect挂载实现
packages/react/src/ReactHooks.js
js
export function useEffect(create) {
const dispatcher = resolveDispatcher();
return dispatcher.useEffect(create);
}packages/react/src/React.js
js
import { useReducer, useState, useEffect } from './ReactHooks';
import ReactSharedInternals from './ReactSharedInternals';
export {
useReducer,
useState,
useEffect,
ReactSharedInternals as __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED
}packages/react/index.js
js
export {
__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED,
useState,
useReducer,
useEffect
}packages/react-reconciler/src/ReactFiberHooks.js
js
import { Passive as PassiveEffect } from './ReactFiberFlags';
import { HasEffect as HookHasEffect, Passive as HookPassive } from './ReactHookEffectTags';
const HooksDispatcherOnMount = {
useReducer: mountReducer, // 在mount期间,使用mountReducer处理useReducer
useState: mountState,
useEffect: mountEffect
}
const HooksDispatcherOnUpdate = {
useReducer: updateReducer,
useState: updateState,
useEffect: updateEffect
}
function mountEffect(create, deps) {
return mountEffectImpl(PassiveEffect, HookPassive, create, deps);
}
function mountEffectImpl(fiberFlags, hookFlags, create, deps) {
const hook = mountWorkInProgressHook();
const nextDeps = deps === undefined ? null : deps;
currentlyRenderingFiber.flags |= fiberFlags;
hook.memoizedState = pushEffect(HookHasEffect | hookFlags, create, undefined, nextDeps);
}
function pushEffect(tag, create, destroy, deps) {
const effect = {
tag,
create,
destroy,
deps,
next: null
}
let componentUpdateQueue = currentlyRenderingFiber.updateQueue;
if (componentUpdateQueue === null) {
componentUpdateQueue = createFunctionComponentUpdateQueue();
currentlyRenderingFiber.updateQueue = componentUpdateQueue;
componentUpdateQueue.lastEffect = effect.next = effect;
} else {
const lastEffect = componentUpdateQueue.lastEffect;
if (lastEffect === null) {
componentUpdateQueue.lastEffect = effect.next = effect;
} else {
const firstEffect = lastEffect.next;
lastEffect.next = effect;
effect.next = firstEffect;
componentUpdateQueue.lastEffect = effect;
}
}
return effect;
}
function createFunctionComponentUpdateQueue() {
return {
lastEffect: null
}
}packages/react-reconciler/src/ReactFiberFlags.js
js
export const Passive = 0b00000000000000010000000000;packages/react-reconciler/src/ReactHookEffectTags.js
js
export const NoFlags = 0b0000;
export const HasEffect = 0b0001;
export const Layout = 0b0100;
export const Passive = 0b1000;