- Context
- 从树里自动传递info
- 父子耦合
- 在生命周期方法里引用 context
- 在无状态函数组件里引用 context
- 什么时候不用 context
- 已知的限制
Context
React最大的优势之一是他很容易从你的React组件里跟踪数据流动。当你看着一个组件,你可以很容易准确看出哪个props被传入,这让你的APP很容易推断。
偶尔,你想通过组件树传递数据,而不在每一级上手工下传prop,React的 “context” 让你做到这点。
> 注意:
>
> Context是一个先进的实验性特性.这个 API 很可能在未来版本变化.
>
大多数应用将不会需要用到 context. 尤其是如果你刚开始用React,你很可能不会想用 context.使用 context 将会使你的代码很难理解因为它让数据流不清晰.它类似于在你的应用里使用全局变量传递state.
如果你必须使用 context ,保守的使用它
不论你正在创建一个应用或者是库,试着分离你对 context 的使用到一个小区域,并尽可能避免直接使用 context API,以便在API变动时容易升级.
从树里自动传递info
假设你有一个这样的结构:
var Button = React.createClass({render: function() {return (<button style={{'{{'}}background: this.props.color}}>{this.props.children}</button>);}});var Message = React.createClass({render: function() {return (<div>{this.props.text} <Button color={this.props.color}>Delete</Button></div>);}});var MessageList = React.createClass({render: function() {var color = "purple";var children = this.props.messages.map(function(message) {return <Message text={message.text} color={color} />;});return <div>{children}</div>;}});
在这里例子里,我们手工穿透一个 color prop 以便于恰当格式化 Button 和 Message 组件.主题是一个很好的例子,当你可能想整个子树都可以访问一部分信息时(比如color). 使用 context 我们可以自动传过这个树:
var Button = React.createClass({contextTypes: {color: React.PropTypes.string},render: function() {return (<button style={{'{{'}}background: this.context.color}}>{this.props.children}</button>);}});var Message = React.createClass({render: function() {return (<div>{this.props.text} <Button>Delete</Button></div>);}});var MessageList = React.createClass({childContextTypes: {color: React.PropTypes.string},getChildContext: function() {return {color: "purple"};},render: function() {var children = this.props.messages.map(function(message) {return <Message text={message.text} />;});return <div>{children}</div>;}});
通过添加 childContextTypes 和 getChildContext 到 MessageList ( context 提供),React下传信息到子树中的任何组件(在这个例子中, Button可以由定义 contextTypes来访问它).
如果 contextTypes 没有定义,那么 this.context 将是一个空对象.
父子耦合
Context 同样可以使你构建这样的 APT:
<Menu><MenuItem>aubergine</MenuItem><MenuItem>butternut squash</MenuItem><MenuItem>clementine</MenuItem></Menu>
通过在 Menu 组件下传相关的信息,每个 MenuItem 可以与包含他们的 Menu 组件沟通.
在你用这个API构建组件以前,考虑一下是否有清晰的替代方案 我们 喜欢像这样简单的用数组传递items:
<Menu items={['aubergine', 'butternut squash', 'clementine']} />
记住你同样可以在props里传递整个React组件,如果你想.
在生命周期方法里引用 context
如果 contextTypes 在一个组件中定义,接下来的生命周期方法会收到一个额外的参数, context 对象:
void componentWillReceiveProps(object nextProps, object nextContext)boolean shouldComponentUpdate(object nextProps, object nextState, object nextContext)void componentWillUpdate(object nextProps, object nextState, object nextContext)void componentDidUpdate(object prevProps, object prevState, object prevContext)
在无状态函数组件里引用 context
无状态函数同样能够引用 context 如果 contextTypes 被定义为函数的属性.下面的代码展示了被写为无状态函数组件的 Button 组件.
function Button(props, context) {return (<button style={{'{{'}}background: context.color}}>{props.children}</button>);}Button.contextTypes = {color: React.PropTypes.string};
什么时候不用 context
正像全局变量是在写清晰代码时最好要避免的,你应该在大多数情况下避免使用context. 特别是,在用它来”节省输入”和代替显示传入props时要三思.
context最好的使用场景是隐式的传入登录的用户,当前的语言,或者主题信息.要不然所有这些可能就是全局变量,但是context让你限定他们到一个单独的React树里.
不要用context在组件里传递你的模型数据.通过树显示的传递你的数据更容易理解.使用context使你的组件更耦合和不可复用,因为 依赖于他们在哪里渲染,他们会表现不同的行为.
已知的限制
如果一个由组件提供的context值变动,使用那个值的子级不会更新,如果一个直接的父级从 shouldComponentUpdate 返回 false .详见 issue #2517 .
