React Context

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

1. 何时使用 Context

通常,在一颗组件树中,如果最上层的状态,要传递到子孙组件中,那么需要中间的父级节点都将 props 进行传递:

export default function App () {
  const [theme, setTheme] = useState('dark')
  const clickHandle = () => {
    if (theme === 'dark') {
      setTheme('light')
    } else {
      setTheme('dark')
    }
  }
  return <div>
    <div onClick={clickHandle}>change theme</div>
    <Parent theme={theme} />
  </div>
}

function Parent ({ theme }) {
  return <Child theme={theme} />
}

function Child ({ theme }) {
  return <div>{theme}</div>
}

上面这个例子,Parent 本身并不需要 theme 这个 props,只是为了传递给子组件,所以进行一个透传

而使用 context, 就能避免透传的问题,中间元素不需要传递 props 。

2. 注意事项

  • 一个订阅了 Context 对象的组件(即 static contextType 等于某个 Context 对象),那么这个组件就会 从父级组件中,匹配离自己最近 的 Context.Provider 提供的值

  • 当没有从父级组件中,匹配到 Context.Provider 时,将会使用 React.createContext(默认值) 的默认值,Context.Provider 提供 undefined 时, React.createContext(默认值) 的默认值 不会生效

  • Provider 接受 value 属性,传递给消费组件,**一个 Provider 可以有多个消费组件,多个 Provider 也可以嵌套使用,消费组件会使用最近的 Provider

    数据**

  • 当 Provider 的 value 发生变化时,内部所有消费组件都会重新渲染,重新渲染不受shouldComponentUpdate 影响

  • 检测 Provider 的 value 发生变化是根据 Object.is 函数

3. Context.Consumer

在刚刚的例子中,Child 组件获取读取 context 的值,是通过指定 static contextType 来实现的

而实际上,我们还可以通过 Context.Consumer 的方式,这是一种 render props 的实现:

4. 示例

4.1 动态 Context

其实我们刚刚的例子都是 动态 Context 的例子:

即 Provider 提供的值,是一个变量,它取决于 父组件的state, 而父组件的 state 是可以随时变的。

与之对应的是 静态 Context

4.2 在嵌套组件中更新 Context

之前的例子,改变 Provider.value 的值 都是发生在顶层组件的,但是我们会有在嵌套组件中,改变 Provider.value 的需求,于是就有这个示例。

4.3 嵌套的 Context

刚刚提到多个 Provier 可以嵌套使用,以上就是嵌套使用的例子。

5. 过时的 API

官方文档

在 过时的 API 中,以上 四个必须 是必须要有的。

参考文档

  1. React 官方文档 Context

Last updated

Was this helpful?