Appearance
上下文 Context
执行栈环境
注意: 这个执行栈环境 不是函数的上下文,也不是 createContext这个上下文。
这是React中将整个执行过程区分为不同的上下文环境,具体可以分为
js
export const NoContext = /* */ 0b0000000;
// 批量更新的 渲染执行栈环境 著名的 unstable_batchedUpdates 、setState
const BatchedContext = /* */ 0b0000001;
// 事件
const EventContext = /* */ 0b0000010;
const DiscreteEventContext = /* */ 0b0000100;
// Legacy模式下 render的同步渲染执行栈环境
const LegacyUnbatchedContext = /* */ 0b0001000;
// Render执行栈环境 beginWork、completeWork()阶段执行的上下文
const RenderContext = /* */ 0b0010000;
// 渲染执行栈环境 commit()阶段执行的上下文
const CommitContext = /* */ 0b0100000;
CommitContext
commit阶段的执行栈环境(这个环境是不可以被任务队列打断的)
RenderContext
render 阶段的执行栈环境,这边涉及到一个问题:
为什么React的任务是异步可中断。具体可以看 React异步可中断
LegacyUnbatchedContext
legacy模式下 在初始化渲染的时候 会不执行批量更新,从而尽快渲染并不能被打断。这就是ReactDOM.render()是同步的原因。
js
function legacyRenderSubtreeIntoContainer(
parentComponent: ?React$Component<any, any>,
children: ReactNodeList,
container: Container,
forceHydrate: boolean,
callback: ?Function,
) {
if (!root) {
// Initial mount should not be batched.
// 初始渲染 不执行批量更新,需要尽快渲染并不能被打断
unbatchedUpdates(() => {
updateContainer(children, fiberRoot, parentComponent, callback);
});
} else {
// Update
updateContainer(children, fiberRoot, parentComponent, callback);
}
return getPublicRootInstance(fiberRoot);
}
在初次渲染的时候 updateContainer的函数是执行在 unbatchedUpdates中的
js
/**
* 设置为 任务同步执行的执行栈环境
* @param {*} fn
* @param {*} a
* @returns
*/
export function unbatchedUpdates<A, R>(fn: (a: A) => R, a: A): R {
// 缓存之前的执行栈环境
const prevExecutionContext = executionContext;
executionContext &= ~BatchedContext;
// 通过 按位与 设置为 任务同步执行的执行栈环境
executionContext |= LegacyUnbatchedContext;
try {
return fn(a);
} finally {
executionContext = prevExecutionContext;
if (executionContext === NoContext) {
// Flush the immediate callbacks that were scheduled during this batch
resetRenderTimer();
flushSyncCallbackQueue();
}
}
}
BatchedContext
批量更新的执行栈环境
对于这个环境,我们看的最多的就是 setState方法 和 React.unstable_batchedUpdates()