React 之 Context

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

使用场景

对一个组件树间而言是“全局”的数据,Context 为组件树提供这个”全局”数据。比如:

  • 当前认证用户信息
  • 网站主题
  • 国际化,首选语言

官方示例:主题

import React from 'react'


// 为当前 theme 创建一个 context,默认值为 light
const ThemeContext = React.createContext('light')

class App extends React.Component {
  render() {
    // 使用一个 Provider 来将当前的 theme 传递给以下的组件树。
    // 无论多深,任何组件都能读取这个值。
    // 在这个例子中,我们将 “dark” 作为当前的值传递下去。
    return <ThemeContext.Provider value='dark'>
      	<Toolbar />
      </ThemeContext.Provider>
  }
}

class ThemeButton extends React.Component {
  // 指定 contextType 读取当前的 theme context
  // React 会往上找到最近的 theme Provider,然后使用它的值
  // 在这个例子中,当前的 theme Provider 的值是 dark
  static contextType = ThemeContext
  
  render() {
    return <Button theme={this.context} />
  }
}

// 中间组件不需要往下传递 theme
function Toolbar() {
  return <di>
    	<ThemeButton />
    </div>
}
复制代码

API

创建 Context:React.createContext

const MyContext = React.createContext(defaultValue)
复制代码

创建一个 Context 对象。

只有当订阅了 Context 对象的组件没有在组件树中匹配到 Provider 时,defaultValue 才会生效。

提供 Context:Context.Provider

  • Context.Provider 是一个组件,允许消费组件(要使用 context 的组件)订阅 context 的变化。
  • Provider 提供一个 value 属性,覆盖 defaultValue,并传递给消费组件。
  • Provider 可以嵌套使用,内层的 value 覆盖外层的 value
  • Provider 的 value 发生变化时,内层的消费组件都会重新渲染。
  • Provider 及其内部的消费组件都不受制于 shouldComponentUpdate 函数,因此当 消费组件在其祖先组件退出更新的情况下也能更新。

使用 Context 1:Class.contextType

在 class 组件中,把 Context 对象初始化给 class 组件的 contextType属性(该属性是定义在 class,是静态属性),然后在 class 内部通过 this.context 来使用 Provider 上的 value 值。

这个 context 在 class 组件内部任何生命周期中都能访问到。

两种初始化 class context 方法:

  • 挂在 class 名上的方式
class MyClass extends React.Component {
  render () {
    const value = this.context
  }
}
MyClass.contextType = MyContext
复制代码
  • 通过 static 定义类的静态属性方式
class MyClass extends React.Component {
  static contextType = MyContext
  render () {
    const value = this.context
  }
}
复制代码

使用 Context 2:Context.Consumer

Context.Consumer 是一个组件,其子元素是一个返回 React 节点的函数,该函数的参数是最近的一个 Provider 的 value。

上述主题按钮可写成:

function ThemeButton() {
  return <ThemeContext.Consumer>
    { value => <Button theme={value} />}
  </ThemeContext.Consumer>
}
复制代码

开发工具:Context.displayName

Context.displayName 用于设置在 React.DevTools 中显示的组件名称。

Context 的多种应用形式

  • 动态 context
  • 在嵌套组件中更新 context,context 的 value 是一个对象格式,包含值和改变值的函数
const ThemeContext = React.createContext({
  theme: 'dark',
  toggleTheme: () => {}
})
复制代码
  • 消费多个 context

注意事项

  • 当 context 的值是一个对象时,容易触发意外的渲染,可以把状态提升至父组件进行集中管理。

おすすめ

転載: juejin.im/post/7074771700985888804