React 新context api
一:舊Context API
// 傳遞者,生成資料並放入context中 class DeliverComponent extends Component { getChildContext() { return { color: "purple" }; } render() { return <MidComponent /> } } DeliverComponent.childContextTypes = { color: PropTypes.string }; // 中間與context無關的元件 const MidComponent = (props) => <ReceiverComponent />;// 接收者,需要用到context中的資料 const ReceiverComponent = (props, context) => <div style={{ color: context.color }}> Hello, this is receiver. </div>; ReceiverComponent.contextTypes = { color: PropTypes.string }; ReactDOM.render( <DeliverComponent> <MidComponent> <ReceiverComponent /> </MidComponent> </DeliverComponent>, 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 (
<Provider value={this.state}>
<MidComponent />
</Provider>
)
}
}
// 中間與context無關的元件
const MidComponent = (props) => <ReceiverComponent />;
// 接收者,需要用到context中的資料
const ReceiverComponent = (props) => (
<Consumer>
{context => (
<div style={{ color: context.color }}> Hello, this is receiver. </div>
)}
</Consumer>
);
ReactDOM.render(
<DeliverComponent>
<MidComponent>
<ReceiverComponent />
</MidComponent>
</DeliverComponent>, 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 模式。