Context
React 遵循 Flux 思想進行數據流傳遞的時候,常見的方式是通過props 逐層從父級向子組件傳遞。
context 是實驗功能,可以簡化傳遞過程,尤其是組件樹層數很多的時候,但是不容易發現傳遞的流向,所以謹慎使用
傳統的props傳值
class Button extends React.Component {
render() {
return (
<button style={{background: this.props.color}}>
{this.props.children}
</button>
);
}
}
class Message extends React.Component {
render() {
return (
<div>
{this.props.text} <Button color={this.props.color}>Delete</Button>
</div>
);
}
}
class MessageList extends React.Component {
render() {
const color = "purple";
const children = this.props.messages.map((message) =>
<Message text={message.text} color={color} />
);
return <div>{children}</div>;
}
}
這個例子中,就是從Message 組件傳遞button
組件的 color
屬性來實現主題控制,整個傳遞過程有些繁瑣,如果使用context,代碼如下:
class Button extends React.Component {
render() {
return (
<button style={{background: this.context.color}}>
{this.props.children}
</button>
);
}
}
Button.contextTypes = {
color: React.PropTypes.string
};
class Message extends React.Component {
render() {
return (
<div>
{this.props.text} <Button>Delete</Button>
</div>
);
}
}
class MessageList extends React.Component {
getChildContext() {
return {color: "purple"};
}
render() {
const children = this.props.messages.map((message) =>
<Message text={message.text} />
);
return <div>{children}</div>;
}
}
MessageList.childContextTypes = {
color: React.PropTypes.string
};
通過給MessageList 添加childContextTypes
和 getChildContext
,可以自動在組件樹的運行上下文環境中傳遞值,作爲父級設置值的時候,父級組件只能以類的形式聲明,無狀態函數式聲明不可以。
子組件隨後就可以使用context
獲取,但是必須定義 contextTypes
,負責獲取的是空對象。組件的聲明就沒有父組件的限制,可以是無狀態函數式(stateless functional),或類。
各組件生命週期方法中的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樣例:
const Button = ({children}, context) =>
<button style={{background: context.color}}>
{children}
</button>;
Button.contextTypes = {color: React.PropTypes.string};
更新context
當state
和props
改變時會自動調用getChildContext
,爲了更新context
中的數據,可以使用this.setState
來觸發局部state
更新,這種更新會傳遞到所有子節點。
class MediaQuery extends React.Component {
constructor(props) {
super(props);
this.state = {type:'desktop'};
}
getChildContext() {
return {type: this.state.type};
}
componentDidMount() {
const checkMediaQuery = () => {
const type = window.matchMedia("(min-width: 1025px)").matches ? 'desktop' : 'mobile';
if (type !== this.state.type) {
this.setState({type});
}
};
window.addEventListener('resize', checkMediaQuery);
checkMediaQuery();
}
render() {
return this.props.children;
}
}
MediaQuery.childContextTypes = {
type: React.PropTypes.string
};
如果沒看懂或者有任何,可以看看facebook 原版文章,歡迎留言交流