React基础(四)Context上下文 简单使用

1,726 阅读4分钟

Context

用法

不想在组件树中通过逐层传递Props的方式来传递数据。可以使用Context来实现跨层级的组件数据传递。
context提供了一个无需为每层组件手动添加props,就能在组件树之间进行数据传递的方法。
Context提供了一种在组件之间共享此类值的方式,而不需要显示地通过组件树的逐层传递props。

何时使用

Context设计目的是为了共享那些对于一个组件树而言是 全局 的数据。例如当前认证的用户,主题或者首选语言。

// demo: 通过一个theme属性改变按钮的样式
// 组件嵌套  App=>ToolBar => ThemeButton

// 不使用context
class App extends Component{
	render(){
  	return(
    	<ToolBar theme = "dark" />
    )
  }
}
function ToolBar(props){
	return (
  	<div>
    	<ThemeButton theme ={ props.theme} />
    </div>
  )
}
class ThemeButton extends React.Component{
	render(){
  	return <Button  theme={ this.props.theme}/>
  }
}
 

如何使用

如果要Context发挥作用,需要用到两种组件,一个是Context生产者,通常是一个父节点。另一个是Context的消费组件。通常是一个或者多个子节点。所以Context的使用基于生产者消费者模式。

使用context,可以避免中间元素传递props
使用步骤:

  1. 引入context  使用React.createContext(value) 方法,参数为要共享的属性的属性值,属性名可以自定义保存

const ThemeContext = React.createContext('light')

  1. 使用Provider将当前的theme传递给以下的组件树。(需要共享某个属性的组件的最外层)

<ThemeContext.Provider value = "dark">  要共享状态的组件 </ThemeContext.Provider>
属性value 为要默认值

  1. 使用值

在组件树中,要使用共享属性的组件才需要做处理, 不使用的组件不做处理。
在需要的组件内,定义静态变量 接收context
static contextType = ThemeContext
共享属性就是需要使用组件上的一个属性,属性值要设置为我们需要用到的属性
    属性值 可以通过 this.context 获取

// Context 可以让我们无需明确地传遍每一个组件,就能将值深入传递进组件树。
// 为当前的theme创建一个context(light 为默认值)
const ThemeContext = React.createContext('light')
class App extends React.Component{
	render(){
  	return (
    	<ThemeContext.Provider value ="dark" >
      	<Toolbar />
      </ThemeContext.Provider>
    )
  }
}
// 中间的组件也无需指明往下传递theme
function Toolbar(props){
	return (
  	<div> 
    	<ThemeButton>
    </div>
  )
}
class ThemeButton extends React.Component{
	// 指定contextType读取当前的 theme context
  // React会往上找到当前的theme Provider 然后使用它的值
  static contextType = ThemeContext
	render(){
  	return <Button theme ={ this.context }>
  }
}

API

React.createContext

语法

const MyContext = React.createContext(defaultValue)

使用

创建一个Context对象,当React渲染了一个订阅了这个Context对象的组件,这个组件会从组件的树中里自身最近的那个匹配的Provider中读取到当前的context值。
只有当组件所在的树中没有匹配到Provider时,其defaultValue才会生效。这有助于在不适用Provider包装组件的情况下对组件进行测试。

注意

将undefined传给Provider的value时,defaultValue不会生效。

Context.Provider

语法

<MyContext.Provider value = "{ /* 某个值 */}">

每个Context对象都会返回一个Provider React组件。,允许消费者组件订阅context的变化
Provider接收一个value属性,传递给子组件,这个消费者组件为生产者组件的后代组件。
一个生产者组件可以连接多个消费者组件。
生产者组件可以被嵌套以覆盖数中更深层次的值。

每当生产者组件的value属性变化时,所有作为生产者后代的消费者组件都将重新渲染,并且不受shouldComponentUpdate的约束。

Class.contextType

可以为类上的contextType属性分配由React.createContext()创建的Context对象。
分配之后,允许使用this.context 在消费者组件中使用该Context类型的最近的当前值。
可以在任何生命周期方法中引用它,包含render函数

class MyClass extends React.Component {
  componentDidMount() {
    let value = this.context;
    /* perform a side-effect at mount using the value of MyContext */
  }
  componentDidUpdate() {
    let value = this.context;
    /* ... */
  }
  componentWillUnmount() {
    let value = this.context;
    /* ... */
  }
  render() {
    let value = this.context;
    /* render something based on the value of MyContext */
  }
}
MyClass.contextType = MyContext;

总结

如何使用Context

  1. 生产者组件中 创建Context对象  使用React.createContext( defaultValue)
  2. 生产者中 使用 Context.Provider 包裹 消费者组件 ,让消费者组件订阅这个Context对象
  3. 消费者 中 使用类属性  Class.contextType 接收创建好的Context对象  Class.contextType = MyContext
  4. 消费者组件中使用  this.context 来接收该Context类型的最近的当前值