先看个代码:
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} key={index} />
);
return <div>{children}</div>;
}
}
上面的我们给button设置颜色,竟然要从顶层的组件一步一步的通过props传递下去,很烦。
如果是使用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, index) =>
<Message text={message.text} key={index}/>
);
return <div>{children}</div>;
}
}
//重点
MessageList.childContextTypes = {
color: React.PropTypes.string
};
通过childContextTypes和getChildContext给MessageList增加context上下文,React会自动将它传递给子组件,如果子组件设置了contextTypes就会获取到这个上下文。如果子组件的contextTypes没有设置的话,context就会是一个空的。
以上就是context的用法,由此可见在React中很容易根据组件从而跟踪数据流,当你使用一个组件时,可以通过看props来判断用了哪一些东西。
有时候你想直接通过组件树来讲数据传递子元素,而不是通过props一层一层的传递下去,可以使用React提供的contextAPI来处理。
需要注意的是:
1.为什么一般都不使用Context
虽然react提供了context来处理以上事件 ,但是一般情况下是不需要使用这个API的。
如果你想要你的应用尽可能的稳定的话,请不要使用Context,因为这在React属于一种实验性质的API,在未来的React版本中可能被抛弃。
2.父子耦合
context可以让父组件和子组件建立一个直接数据交流的通道,以上代码就实现了这个功能,这里不详讲。
3.在生命周期函数中使用context
需要将context通过参数传递
constructor(props, context)
componentWillReceiveProps(nextProps, nextContext)
shouldComponentUpdate(nextProps, nextState, nextContext)
componentWillUpdate(nextProps, nextState, nextContext)
componentDidUpdate(prevProps, prevState, prevContext)
4.无状态函数式组件中的context
这里先声明一下函数式组件本身无法使用this.state来进行状态标记控制
const Button = ({children}, context) =>
<button style={{background: context.color}}>
{children}
</button>;
Button.contextTypes = {color: React.PropTypes.string};
当我们将context当做参数传入函数式组件,并且contextTypes进行了类型检测控制,就可以在函数式组件内部使用context
5.更新Context
虽然React有更新Context的函数,但是对不起,依旧不希望你去使用context,这算是警告中的警告了。
在前面写的时候,我就已经使用getChildContext来处理数据,这个函数会在state和props改变时被调用。只要对state和props进行更新就可以实现context的更新。