1. 程式人生 > >React 新context api

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 模式。