react 源码解析 17.context
react 源码解析 17.context
视频课程(高效学习):进入课程
课程目录:
查看视频调试 demo_7
context 流程图
![](https://static001.geekbang.org/infoq/28/2877865a54416a545c9e3d5dae2f27fb.png)
![](https://static001.geekbang.org/infoq/6e/6e6798a1a2d4205764c0dca79a0a8936.png)
cursor/valueStack
react 源码中存在一个 valueStack 和 valueCursor 用来记录 context 的历史信息和当前 context,另外还有一个 didPerformWorkStackCursor 用来表示当前的 context 有没有变化
在 render 阶段调用 updateContextProvider 的时候会执行 pushProvider,将新的值 push 进 valueStack 中
在 commit 阶段调用 completeWork 的时候会执行 popProvider,将栈顶 context pop 出来,
为什么会有这样一个机制呢,因为我们的 context 是跨层级的,在之前讲到 render 阶段和 commit 阶段的时候,我们会以深度优先遍历的方式遍历节点,如果涉及跨层级读取状态就有点力不从心了,就需要一层一层往下传递我们的 props,所以我们可以用一个 stack 记录我们的 context,在 render 阶段 pushProvider,在 commit 阶段 popProvider,在每个具体的层级能根据 valueCursor 取当前 value
createContext
在简化之后的 createContext 中可以看到,context 和 Provider、Consumer 的关系是这样的:
useContext
useContext 会调用 readContext,readContext 会创建 dependce,加入当前 fiber 的 dependencies 链表中
provider/customer
在 render 阶段会调用 updateContextProvider,注意几个关键的步骤
pushProvider:将当前 context 加入 valueStack
calculateChangedBits:useContext 可以设置 observedBits,没有设置的话就是 MAX_SIGNED_31_BIT_INT,也就是 31 位 1,用于计算 changedBits,这个计算 context 是否变化的过程就发生在 calculateChangedBits 函数中,用这样的方式可以提高 context 变化之后的性能
bailoutOnAlreadyFinishedWork/propagateContextChange:如果 changedBits 没有改变则走 bailoutOnAlreadyFinishedWork 的逻辑,跳过当前节点的更新,如果改变则执行 propagateContextChange
updateContextConsumer 关键的代码如下,执行 prepareToReadContext 判断优先级是否足够加入当前这次 render,readContext 取到当前 context 的 value
版权声明: 本文为 InfoQ 作者【全栈潇晨】的原创文章。
原文链接:【http://xie.infoq.cn/article/901126b9e2672f27465689c7e】。文章转载请联系作者。
评论