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 原版文章,欢迎留言交流