React context
关于context的官方文档
https://reactjs.org/docs/context.html
这个网址可能要番羽土廧
简单解释一下,context就相当于一个全局变量一样的,在一个组件树中,根组件传递值或者方法给子孙后代组件,需要一层一层的传,相当麻烦。
而这个context,定义了组件树的共享上下文,使得传递值,不需要经过中间组件,也有人戏称为react中的虫洞。
React context的API有两个版本,React16.x之前的是老版本的context,之后的是新版本的context。
先来学习老版本的怎么用
先来定义一个根组件A,然后getChildContext是固定的api接口,定义全局共享的上下文,这个return的对象里面塞入的是你要传递的东西(比如说这里传递的是user这个人的信息给子孙组件)
class A extends React.Component {
getChildContext() {
return {
user: this.props.user,
text: "item text"
}
}
render() {
<div>{this.props.children}</div>
}
}
A.childContextTypes = {
user: React.PropTypes.object.isRequired,
text:React.PropTypes.string.isRequired
}
要在后面指定组件A的传入验证A.childContextTypes,不指定的话,会产生错误
然后在后代组件中这样使用(这里我们定义一个组件D,是根组件A的后代元素)
class D extends React.Component {
render() {
<div>{this.context.user.name}</div>
}
}
D.contextTypes = {
user: React.PropTypes.object.isRequired
}
这里也要定义D的contextTypes,可以只定义context中的部分,例如我这里,只定义了user,没有定义text,也是ok的,如果这里的contextTypes没有定义,那么用this.context获取到的,将是一个空对象。
从React v15.5开始 ,React.PropTypes 助手函数已被弃用,可使用 prop-types 库 来定义contextTypes
-
老的context 有个问题就是,shouldComponentUpdate这个生命周期函数,一般用来优化性能,减少渲染次数,这个生命周期函数只检测state和prop的值,如果上下文context的值变动了,它并不能检测到,所以就不会render,那么这个组件的子组件,也不会重新render,无法获得新的context的值
-
新版本解决了上面这个问题
那么再来看看新版本怎么使用这个api
新版本的用法有点像react-redux,外层使用Provider包裹,然后在value处注入上下文环境,然后后代组件用Customer包裹,用来接收上下文
import React, { Component } from 'react';
const Test1Context = React.createContext({
user:{name:"asdf"},
text:"asdfdsaf"
});
class A extends React.Component {
state ={
user: this.props.user,
text: "item text"
}
render() {
<Test1Context.Provider value={this.state}>
<div>{this.props.children}</div>
</Test1Context.Provider>
}
}
- React.createContext()传入的东西用于设置默认值,也可以不传。
- 这个包裹的Provider,要改成你定义的上下文名字+.Provider,这里我定义的上下文环境名字叫 Test1Context,所以我render里面包裹的是Test1Context.Provider。
- value里可以放任意的东西,比如放一个对象,放个数组,放个字符、数字,放个function,都ok。
然后再是后代组件D
class D extends React.Component {
render() {
<Test1Context.Consumer>
<div>
{this.context.user.name}
{(value)=><div>value.user.name</div>}
{({user})=><div>user.name</div>}
</div>
</Test1Context.Consumer>
}
}
D.contextType = Test1Context ;
(或者在D里面 static contextType = Test1Context )
可以在生命周期里面使用,官方文档是这样写的
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;