React context 丢失问题
React context 丢失问题
什么是 contextcontext是为了解决component之间通信的上下文机制,该api目前并未定稿所以react并没有开放出来。最近有大量需要共享上下文的场景才去了解这个api,然后也成功被绕了进去.... 问题场景需要在Parent中声明context,在Children中拿到context并打印出来。 var Children = React.createClass({ contextTypes: { value: React.PropTypes.string },render: function() { return <div>{this.context.value || '并没有context'}</div> ; } }); var Parent = React.createClass({ childContextTypes: { value: React.PropTypes.string },getChildContext: function() { return { value: '上下文' }; },render: function() { return ( <div> {this.props.children} </div> ); } }); var App = React.createClass({ render: function() { return ( <Parent> <Children /> </Parent> ); } }); React.render(React.createElement(App),document.body); 这样执行完后屏幕上应该是『上下文』三个打字,但事实是
以及
那么问题来了,上下文为何失效了呢?!为什么Children拿不到Parent里面的context呢?! find the problem各种google之后发现gaearon大神在issue中的回复。
原来现在0.13.3版本的react context的传递规则是owner规则,在刚才的例子中虽然
不继续吐槽,那么按照这个思路把context放在App上,Parent与Children应该都能成功拿到Context了吧。 代码是这样的: var Parent = React.createClass({ contextTypes: { value: React.PropTypes.string },render: function() { return ( <div> {this.context.value && '可算拿到了...' } {this.props.children} </div> ); } }); var App = React.createClass({ childContextTypes: { value: React.PropTypes.string },render: function() { return ( <Parent> <Children /> </Parent> ); } }); React.render(React.createElement(App),document.body); 结果是这样的:
看来context成功被拿到,看到这里大家应该明白React context的机制了把。 how to get parent context虽然明白了原理,但是问题并没有解决。我就是希望Chilren拿到Parent中的context,而不是拿到App中的context啊。我目前一共找到了两种方式可以在现阶段获取parent context。 1. use the callback通过接收回调函数而不是react.element,然后在Parent中进行render,那么render的内容的owner自然就是Parent了,从而可以成功拿到Parent中的context。 var Parent = React.createClass({ childContextTypes: { value: React.PropTypes.string },render: function() { return ( <div> {this.props.children() /* 注意这里是function,需要执行 */} </div> ); } }); // parent接受回调函数,回调函数中的内容owner为parent var App = React.createClass({ render: function() { return ( <Parent> {this.renderChild} </Parent> ); },renderChild: function() { return <Children />; } }); 实测可以成功拿到context。 2.通过this._reactInternalInstance这种方法虽然用起来很方便不过健壮性很差,等react更新之后没准又得改代码~ var Children = React.createClass({ contextTypes: { value: React.PropTypes.string },render: function() { return <ul> <li>{'default context is: ' + this.context.value}</li> <li>{'parent context: ' + this._reactInternalInstance._context.value}</li> <li>{'owner context: ' + this._reactInternalInstance._currentElement._context.value}</li> </ul> ; } }); var Parent = React.createClass({ childContextTypes: { value: React.PropTypes.string },getChildContext: function() { return { value: 'parent' }; },render: function() { return ( <div> {this.props.children} </div> ); } }); var App = React.createClass({ childContextTypes: { value: React.PropTypes.string },getChildContext: function() { return { value: 'app' }; },render: function() { return ( <Parent> <Children /> </Parent> ); },}); React.render(React.createElement(App),document.body); 结果如下:
context es6 写法由于同事问我es6下context怎么用,想到可能有些人也不清楚,在这里一并附上。个人不推荐使用es7语法。 import React from 'react'; class Children extends React.Component { // 如果不需要在构造函数中使用可以不写,没有影响 constructor(props,context) { super(props,context); console.log(context); } render() { return <ul> <li>{'default context is: ' + this.context.value}</li> <li>{'parent context: ' + this._reactInternalInstance._context.value}</li> <li>{'owner context: ' + this._reactInternalInstance._currentElement._context.value}</li> </ul> ; } } Children.contextTypes = { value: React.PropTypes.string }; class Parent extends React.Component { getChildContext() { return { value: 'parent' }; } render() { return ( <div> {this.props.children} </div> ); } } Parent.childContextTypes = { value: React.PropTypes.string }; class App extends React.Component { getChildContext() { return { value: 'app' }; } render() { return ( <Parent> <Children /> </Parent> ); } } App.childContextTypes = { value: React.PropTypes.string }; React.render(React.createElement(App),document.body); (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |