React笔记——高级指引:3.Context

Context提供了一个无需为每层组件手动添加props,就能在组件树间进行数据传递的方法。

1.何时使用Context

Context设计目的是为了共享那些对于一个组件树而言是“全局”的数据。

1.1 传统写法

1.2 使用context

2.使用Context之前的考虑

Context主要应用场景在于很多不同层级的组件需要访问同样的一些数据。需要谨慎使用,因为这样会使得组件的复用性变差

如果你只是想避免层层传递一些属性,组件组合(component composition)有时候是一个比 context 更好的解决方案。

2.1 组件组合创建Page组件示例

3.API

3.1 React.createContext

  • 语法:

创建一个 Context 对象。当 React 渲染一个订阅了这个 Context 对象的组件,这个组件会从组件树中离自身最近的那个匹配的 Provider 中读取到当前的 context 值。

只有当组件所处的树中没有匹配到 Provider 时,其 defaultValue 参数才会生效。这有助于在不使用 Provider 包装组件的情况下对组件进行测试。注意:将 undefined 传递给 Provider 的 value 时,消费组件的 defaultValue 不会生效。

  • 示例:


3.2 Context.Provider

  • 语法:

  • 每个 Context 对象都会返回一个 Provider React 组件,它允许消费组件订阅 context 的变化。
  • Provider 接收一个 value 属性,传递给消费组件。一个 Provider 可以和多个消费组件有对应关系。多个 Provider 也可以嵌套使用,里层的会覆盖外层的数据。
  • 当 Provider 的 value 值发生变化时,它内部的所有消费组件都会重新渲染。Provider 及其内部 consumer 组件都不受制于 shouldComponentUpdate 函数,因此当 consumer 组件在其祖先组件退出更新的情况下也能更新。

3.3 Class.contextType

挂载在 class 上的 contextType 属性会被重赋值为一个由 React.createContext() 创建的 Context 对象。这能让你使用 this.context 来消费最近 Context 上的那个值。你可以在任何生命周期中访问到它,包括 render 函数中。

如果你正在使用实验性的 public class fields 语法,你可以使用 static 这个类属性来初始化你的 contextType

3.4 Context.Consumer

语法:

这需要函数作为子元素(function as a child)这种做法。这个函数接收当前的 context 值,返回一个 React 节点。传递给函数的 value 值等同于往上组件树离这个 context 最近的 Provider 提供的 value 值。如果没有对应的 Provider,value 参数等同于传递给 createContext() 的 defaultValue


3.5 Context.displayName

context 对象接受一个名为 displayName 的 property,类型为字符串。React DevTools 使用该字符串来确定 context 要显示的内容。

4.示例

4.1 动态Context




4.2 在嵌套组件中更新Context



4.3 使用多个Context

5.注意事项

因为 context 会使用参考标识(reference identity)来决定何时进行渲染,这里可能会有一些陷阱,当 provider 的父组件进行重渲染时,可能会在 consumers 组件中触发意外的渲染。举个例子,当每一次 Provider 重渲染时,以下的代码会重渲染所有下面的 consumers 组件,因为 value 属性总是被赋值为新的对象:

为了防止这种情况,将 value 状态提升到父节点的 state 里:

6.废弃的API