文本是爲了說清
react context
目前的機制是owner context
而不是咱們覺得的parent context
機制,並說明這二者的區別。但願能對即將使用context的同窗有所幫助.html
context是爲了解決component之間通訊的上下文機制,該api目前並未定稿因此react並無開放出來。最近有大量須要共享上下文的場景纔去瞭解這個api,而後也成功被繞了進去....
介紹與用法這篇文章Introduction to Contexts in React.js說得很清楚~react
須要在Parent中聲明context,在Children中拿到context並打印出來。git
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);
這樣執行完後屏幕上應該是『上下文』三個打字,但事實是es6
以及warning
github
那麼問題來了,上下文爲什麼失效了呢?!爲何Children拿不到Parent裏面的context呢?!api
各類google以後發現gaearon大神在issue中的回覆。app
原來如今0.13.3版本的react context的傳遞規則是owner規則,在剛纔的例子中雖然Children
的parent爲Parent
,可是App
纔是Children
與parent共同的owner,this.context只能拿到owner傳遞規則的context。函數
尼瑪,跟想象中的不同啊!你props、render的規則不都是Parent規則麼!this
不繼續吐槽,那麼按照這個思路把context放在App上,Parent與Children應該都能成功拿到Context了吧。google
代碼是這樣的:
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 }, getChildContext: function() { return { value: '上下文' }; }, render: function() { return ( <Parent> <Children /> </Parent> ); } }); React.render(React.createElement(App), document.body);
結果是這樣的:
看來context成功被拿到,看到這裏你們應該明白React context的機制了把。
雖然明白了原理,可是問題並無解決。我就是但願Chilren拿到Parent中的context,而不是拿到App中的context啊。我目前一共找到了兩種方式能夠在現階段獲取parent context。
經過接收回調函數而不是react.element,而後在Parent中進行render,那麼render的內容的owner天然就是Parent了,從而能夠成功拿到Parent中的context。
var Parent = React.createClass({ childContextTypes: { value: React.PropTypes.string }, getChildContext: function() { return { value: '上下文' }; }, 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。
這種方法雖然用起來很方便不過健壯性不好,等react更新以後沒準又得改代碼~
能夠經過this._reactInternalInstance._context.value
拿到該element的parent context。this._reactInternalInstance._currentElement._context.value
就是默認的owner context。
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);
結果以下:
因爲同事問我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);