一:旧Context API
// 传递者,生成数据并放入context中
class DeliverComponent extends Component {
getChildContext() {
return { color: "purple" };
}
render() {
return
}
}
DeliverComponent.childContextTypes = {
color: PropTypes.string
};
// 中间与context无关的组件
const MidComponent = (props) => ;// 接收者,需要用到context中的数据
const ReceiverComponent = (props, context) =>
Hello, this is receiver. ;
ReceiverComponent.contextTypes = {
color: PropTypes.string
};
ReactDOM.render(
, document.getElementById('root'));
可以看到,使用context api可以把DeliverComponent中的参数color直接跨越MidComponent传递到ReceiverComponent中,不需要冗余的使用props参数传递,特别是ReceiverComponent层级特别深的时候,使用context api能够很大程度上节省重复代码避免bug。
旧Context API的缺陷
1.代码冗余:提供context的组件要定义`childContextTypes`与`getChildContext`才能把context传下去。同时接收context的也要先定义contextTypes才能正确拿到数据。
2.传递效率:虽然功能上context可以跨层级传递,但是本质上context也是同props一样一层一层的往下传递的,当层级过深的时候还是会出现效率问题。
3.shouldComponentUpdate:由于context的传递也是一层一层传递,因此它也会受到shouldComponent的阻断。换句话说,当传递组件的context变化时,如果其下面某一个中间组件的shouldComponentUpdate方法返回false,那么之后的接收组件将不会收到任何context变化。
二、新Context API
React自16.3开始提供了一个新的context api, 新的context api可以直接将context数据传递到传递到子组件中而不需要像旧context api那样级联传递
import React, { Component, createContext } from 'react';
const DEFAULT_STATE = {color: 'red'};
const { Provider, Consumer } = createContext(DEFAULT_STATE);// 传递者,生成数据并放context中
class DeliverComponent extends Component {
state = { color: "purple" };
render() {
return (
)
}
}
// 中间与context无关的组件
const MidComponent = (props) => ;
// 接收者,需要用到context中的数据
const ReceiverComponent = (props) => (
{context => (
Hello, this is receiver.
)}
);
ReactDOM.render(
, document.getElementById('root'));
可以看到新的context api主要包含一个Provider和Consumer对,在Provider输入的数据可以在Consumer中获得。 新context api的要点如下:
1. Provider和 Consumer必须来自同一次 React.createContext调用。也就是说 NameContext.Provider和 AgeContext.Consumer是无法搭配使用的。
2. React.createContext方法接收一个默认值作为参数。当 Consumer外层没有对应的 Provider时就会使用该默认值。
3. Provider 组件的 value prop 值发生变更时,其内部组件树中对应的 Consumer组件会接收到新值并重新执行 children函数。此过程不受 shouldComponentUpdete 方法的影响。
4. Provider组件利用 Object.is 检测 value prop 的值是否有更新。注意 Object.is和 === 的行为不完全相同。
5. Consumer组件接收一个函数作为 children prop 并利用该函数的返回值生成组件树的模式被称为 Render Props 模式。