创建上下文
上下文是一个独立于组件的对象,该对象通过React.createContext(默认值)创建,
返回的是一个包含两个属性的对象,这俩对象是俩React组件
- Provider: 生产者,该组件会创建一个上下文,通过属性value为其数据赋值
注意: 同一个Provider不要用到多个组件当中
- Consumer: 消费者,该组件要求children属性必须传入一个函数,函数返回要显示的内容,上下文数据value会作为第一个参数返回
使用上下文中的数据
- 仅在类组件中, 直接使用this.context获取上下文数据
要求: 必须拥有静态属性contextType,赋值为创建的上下文对象 - 在函数组件或者类组件中,可以使用Consumer来获取上下文
注意细节
如果上下文提供者(Provider)的value属性发生变化(Object.is判断为否),会导致该上下文的所有后代全部重新渲染,就算使用了shouldComponentUpdate优化也不行,原因是强制渲染,不运行shouldComponentUpdate
NewContext.js
import React, { Component } from 'react'
const ctx = React.createContext()
function A(props) {
return (
<div>
<h1>函数组件A</h1>
{/* 函数组件中使用Consumer,类组件中也可以使用 */}
<ctx.Consumer>
{/* value作为参数传递过来 */}
{value => (<h2>a: {value.a}, b: {value.b}</h2>)}
</ctx.Consumer>
<B />
</div>
)
}
class B extends Component {
// 类组件必须定义静态属性contextType,才可以使用this.context,否则要使用Consumer
static contextType = ctx
render() {
return (
<div>
<h1>类组件B context-a: {this.context.a}, context-b: {this.context.b}</h1>
</div>
)
}
}
export default class NewContext extends Component {
state = {
a: 111,
b: "hello"
}
render() {
return (
// 直接传递state会导致在setState的时候无论是否更改context的value值,其子组件都会强制渲染
// 所以推荐在state中定义ctx属性,用于传递,我这就不演示了
<ctx.Provider value={this.state}>
<div>
<A />
<button onClick={()=> {
this.setState({
a: this.state.a + 1
})
}}>更改a</button>
</div>
</ctx.Provider>
)
}
}