React 的 Context

178 阅读2分钟

传递 props 是将数据通过 UI 树显式传递到使用它的组件的好方法。但是当你需要在组件树中深层传递参数以及需要在组件间复用相同的参数时,传递 props 就会变得很麻烦。最近的根节点父组件可能离需要数据的组件很远,状态提升 到太高的层级会导致 “逐层传递 props” 的情况。

image.png


使用 useContext

在一个文件里,用 createContext 创建一个 Context 对象,并导出

供给数据的组件中,使用 CountContext.Provider 去提供此 Context 的值

在子级消费组件中,使用 useContext 这个 Hook 去读取和订阅 Context 的值

image.png


Context 这个设计的内部

存储值

createContext 方法会创建一个 context 对象,包含这些属性:

  • Provider 组件
  • Consumer 组件
  • _currentValue

假如 context 叫 CountContext。CountContext.Provider 接受一个 value,可以将数据向下传递给消费组件。当 value 变化时,所有消费组件会重新渲染

通知变化

当 value 发生变化,在 beginWork (就当成是一个更新流程)阶段识别出这个组件是 ContextProvider 类型,就执行 updateContextProvider 方法

updateContextProvider 中,对新旧 Context Value 进行比较,如果有变化,则使用 propagateContextChange 方法遍历子组件(遍历顺序是子、兄弟、叔的顺序)。遍历后将所有消费了此 Context 的组件标记为可更新

在后续的提交过程中,检查到消费组件的标记后,就会对其更新:查找 CountContext 的 currentValue,并渲染

子组件读取 Context 值

消费 context 有两种方式:useContext / CountContext.Consumer

在消费组件中的 useContext,会执行 readContext 方法,它会为当前组件用到的多个 Context 维护一个链表(commit 后会把这个链表清空),readContext 最后会返回 Context Value


一句话

createContext 时会创建一个 Context 对象,它存有 currentValue 值。消费组件中使用 useContext 时,会返回对应 Context 的 currentValue。当 Context 的 Provider 接受的 value 发生变化时,会去查找子组件内的所有消费组件,将其标记为可更新

geranimo-qzgN45hseN0-unsplash.jpg


参考