react component context

在之前看react-redux时, 说到Provider组件是使用context来实现的, 现在就来看看context到底是个什么东西.

按照官方推荐的意思是, 尽量少使用context, 因为可能会造成应用程序不稳定, 而且作为实验性的 API, 可能会在未来版本移除.

好了, 警告看完了, 下面来继续使用它吧.

基本用法

context是帮助你的应用更简单的传递多层数据的工具. 就如同Provider组件, 提供了一个store``props, 那么它的子级不管多深, 只需要connect一下, 便可以拿到该store, 完全没有props传递链的那种复杂写法.

1
2
3
4
5
6
7
8
9
10
11
12
13
class Provider extends Component {
getChildContext() {
return {
store: this.props.store,
};
}
render() {
return this.props.children;
}
}
Provider.childContextTypes = {
store: PropTypes.object,
};

Provider的实现方法就差不多是这个样子, 通过它来学习context怎么使用. 首先, 提供数据的组件需要实现getChildContext方法, 返回一个对象, 对象值即为能提供的所有属性值, 还需要定义childContextTypes, 表示下级可以获取到的所有属性值. 如果没有定义childContextTypes, 那么下级的context将得到一个空对象.
connect返回的是一个高阶组件, 这个组件定义了contextTypes, 然后就可以在组件相关生命周期函数里面获取到对应的值了.

1
2
3
ConnectComponent.contextTypes = {
store: PropTypes.object.isRequired,
};

生命周期函数

context在如下五个生命周期函数里面都可以获取和使用:

  • constructor(props, context)
  • componentWillReceiveProps(nextProps, nextContext)
  • shouldComponentUpdate(nextProps, nextState, nextContext)
  • componentWillUpdate(nextProps, nextState, nextContext)
  • componentDidUpdate(prevProps, prevState, prevContext)

无状态组件

在无状态组件中也可以使用context, 会和props一样, 作为函数的第二个参数传入.

1
2
3
4
5
6
function FuncComponent(props, context) {
return <div>{this.context.user.name}</div>;
}
FuncComponent.contextTypes = {
user: React.PropTypes.object.isRequired,
};

注意shouldComponentUpdate

props以及state一样, 当上级改变context时候, 会触发下级的相关生命周期函数, 在shouldComponentUpdate返回true时进行重新渲染.
而与propsstate不同的地方在于, context是可以跨组件传递的. 这就意味着, 可能有部分中间的组件并没有使用context, 而它们的propsstate并没有变化, 在shouldComponentUpdate返回false的时候停止了子树的更新, 而子组件是使用context获取上层数据, 但是并没有被触发更新. 这就是为什么react-router需要使用withRouter来包裹connect以后的组件, 因为在connect中实现了shouldComponentUpdate, 会截断子树的render.
所以react官方并不推荐更新context, 它应该作为一个固定的值来被全局使用, 否则可能在某些深层组件可能会出现意外的bug.

作者

Mosby

发布于

2017-08-19

许可协议

评论