Context,React中隐藏的秘密!
brunoyang opened this issue · 14 comments
好吧我承认我是标题党,新人为了导流量蛮拼的。今天我想给大家介绍一下React中的context,本文基于React@0.14。
重要声明:context 相关内容在将来仍有可能会发生变动,所以不建议使用在生产环境中。
什么是context
context是一个将被收录进React1.0的特性,但目前还没有正式地出现在官方文档中。
那什么是context
呢,context
就是一组属性的集合,并被_隐式_地传递给后代组件。
大家可能会有疑惑,我们不是已经有了props
了吗,为什么还需要用context
来传递属性呢。可以考虑这么一个情景,有一个层级很深的组件,最里层组件的行为将影响最外层的表现,一般来说我们就会在最外层组件上绑定回调,再一级一级地传入至最内层组件上,通过触发回调来进行上述行为(这里不考虑用flux)。再考虑另外一个情景,在服务端有一个组件需要根据session来渲染,当内部组件需要获取session信息时,就需要从最上层节点一层一层地往下传。但这样的实现不得不说实在有些丑陋,有没有更好的实现方式呢?有,就是使用context
。
实例
import ReactDOM from 'react-dom';
import React from 'react'
// Children component
class Children extends React.Component {
constructor(props, context) {
super(props, context);
this.state = {
name: this.context.name
};
}
render() {
return(
<ul>
<li>
{`child context is: ${this.context.age}`} // child context is: 18
</li>
<li>
{`state from context: ${this.state.name}`} // state from context: mars
</li>
<li>
{`print age: ${this.context.print(this.context.age)}`} // print age: 18
</li>
</ul>
);
}
}
Children.contextTypes = {
name: React.PropTypes.string,
age: React.PropTypes.number,
print: React.PropTypes.func
};
// Parent component
class Parent extends React.Component {
getChildContext() {
return {
name: 'mars',
age: 18
};
}
render() {
return (
<div>
{`from App component: ${this.context.name}`} // from App component: bruno
<div>
{this.props.children}
</div>
</div>
);
}
}
Parent.contextTypes = {
name: React.PropTypes.string
};
Parent.childContextTypes = {
age: React.PropTypes.number,
name: React.PropTypes.string
};
// App component
class App extends React.Component {
getChildContext() {
return {
name: 'mars',
print: (m) => m
};
}
render() {
return (
<Parent>
<Children />
</Parent>
);
}
}
App.childContextTypes = {
name: React.PropTypes.string,
print: React.PropTypes.func
};
ReactDOM.render(<App />, document.getElementById('app'));
在上面的例子中,我们可以看到在App
组价中声明的print
方法并没有通过Parent
传递,而是通过context
直接传递给了Children
,这大大方便了我们传值的操作,不再需要一遍一遍地写print={this.props.print}
。但同时,我们也需要注意,不要将所有东西都绑定在context
上,而是只在必要时使用context
,毕竟全局变量很危险。
使用方法
使用getChildContext
方法将属性传递给子组件,并使用childContextTypes
声明传递数据类型,子组件中需要显式地使用contextTypes
声明需要用到的属性的数据类型。
需要传递进context参数才可以在constructor方法中使用context,要不然React将会报错。
在组件中,通过this.context访问context中的属性或方法。
相关api
contextTypes
当需要在当前组件使用从上级组件传入的context的属性时,需要为用到的属性声明数据类型
childContextTypes
声明传递给子组件的属性的数据类型。
getChildContext
设置传递给子组件的属性,可以覆盖,也可以新增。
Thanks!
Thanks!
Thanks
thanks
好吧,我承认你是标题党
还有一个属性updater
function ReactComponent(props, context, updater) {
this.props = props;
this.context = context;
this.refs = emptyObject;
// We initialize the default updater but the real one gets injected by the
// renderer.
this.updater = updater || ReactNoopUpdateQueue;
}
thanks
thanks!! It confused me long time!
@chenyulun updater 是内部更新的时候使用的。传入自定义的 updater 的话,基本上说明没有什么必要用 react 了...
thanks!!正好用到这个!
thanks
╰(´︶`)╯♡ 写得很清楚,理解了~
thx
thanks a lot