React中的数据传递----上下文(Context)
2019-01-12 本文已影响2人
w如弈如意c
React如果在整个组件树中传递数据,需要在每一层传递属性(单向数据流,从上往下传递),如果组件套的很深的话,这样传递就非常恶心了。解决这个问题,除了Redux外,你还可以考虑使用强大的”context” API解决这个问题
1.什么时候该使用 Context
官方文档:Context 旨在共享一个组件树内可被视为 “全局” 的数据,例如当前经过身份验证的用户,主题或首选语言等。
2.具体用法
下面是一个简单的上下文使用实例:最外层组件一个color,需要传递给Title组件和Content组件(根组件,绕过子组件,传给孙组件),如下图

基本组件结构如下:
HomePage
class HomePage extends Component {
constructor(props) {
super(props);
this.state ={
color: 'red'
}
}
render() {
return (
<div>
<Header />
<Main />
</div>
)
}
}
Header和Main
class Header extends Component{
render() {
return (
<div>
<Title />
</div>
)
}
}
class Main extends Component{
render() {
return (
<div>
<Content />
</div>
)
}
}
Title和Content
class Title extends Component{
render() {
return (
<div>
这里是标题部分
</div>
)
}
}
class Content extends Component{
render() {
return (
<div>
这里是内容部分
</div>
)
}
}
分一下几步:
- 1:在父组件里定义childContextTypes---子上下文类型
static childContextTypes = {
color: PropTypes.string
}
- 2:在父组件里定义一个getChildContext用来返回上下文对象,返回的属性要和第一步定义类型对应
getChildContext() {
return {
color: this.state.color
}
}
- 3:在这些要接收这些上下文对象的组件里定义contextTypes,这里要节后的组件为Title和Content
static contextTypes ={
color: PropTypes.string
}
这样传递过来,Title和Content就拿到this.context对象,里面包含color属性,则能在Title和Content中使用了
- Title:
render() {
return (
<div style={{color: this.context.color}}>
这里是标题部分
</div>
)
}
- Content
render() {
return (
<div style={{color: this.context.color}}>
这里是内容部分
</div>
)
}
通过以上,就绕过Header和Main,直接将根节点的属性传递到了孙组件Title和Content里面,这样子组件谁想要谁接收这个属性就行了就行了。
接下来考虑如何在孙组件Header或者Content中去改变这个属性呢?
比如在Content组件, 注意:这个属性是根节点的状态,状态是自能自己改的。所以我们需要在根组件,也就是HomePage定义一个个方法,谁需要改,就把这个方法当属性传给谁。
HomePage:
static childContextTypes = {
color: PropTypes.string,
setColor: PropTypes.func
}
getChildContext() {
return {
color: this.state.color,
setColor: this.setColor
}
}
setColor = (color) => {
this.setState({color})
}
接下来在需要改变这个属性子组件接受这个方法:并在事件中调用context的方法
static contextTypes ={
color: PropTypes.string,
setColor: PropTypes.func
}
render() {
return (
<div style={{color: this.context.color}}>
这里是内容部分
<button onClick={() => this.context.setColor('green')}>变为绿色</button>
<button onClick={() => this.context.setColor('yellow')}>变为黄色</button>
</div>
)
}
注意点击事件的写法,确保this指向正确。
- 特别注意:上下文必须父子组件间。react-redux里的Provider是通过上下文实现的