React context基本用法


React的context就是一個全局變量,可以從根組件跨級別在React的組件中傳遞。React context的API有兩個版本,React16.x之前的是
老版本的context,之后的是新版本的context。

1.老版本的context

getChildContext 根組件中聲明,一個函數,返回一個對象,就是context
childContextTypes 根組件中聲明,指定context的結構類型,如不指定,會產生錯誤
contextTypes 子孫組件中聲明,指定要接收的context的結構類型,可以只是context的一部分結構。contextTypes 沒有定義,context將是一個空對象。
this.context 在子孫組件中通過此來獲取上下文
(注:從React v15.5開始 ,React.PropTypes 助手函數已被棄用,可使用 prop-types 庫 來定義contextTypes)

舉例如下:

//根組件
class MessageList extends React.Component {
  getChildContext() {
    return {color: "purple",text: "item text"};
  }

  render() {
    const children = this.props.messages.map((message) =>
      <Message text={message.text} />
    );
    return <div>{children}</div>;
  }
}

MessageList.childContextTypes = {
  color: React.PropTypes.string
  text: React.PropTypes.string
};

//中間組件
class Message extends React.Component {
  render() {
    return (
      <div>
        <MessageItem />
        <Button>Delete</Button>
      </div>
    );
  }
}

//孫組件(接收組件)
class MessageItem extends React.Component {
  render() {
    return (
      <div>
        {this.context.text}
      </div>
    );
  }
}

MessageItem.contextTypes = {
  text: React.PropTypes.string
};

class Button extends React.Component {
  render() {
    return (
      <button style={{background: this.context.color}}>
        {this.props.children}
      </button>
    );
  }
}

Button.contextTypes = {
  color: React.PropTypes.string
};

2.新版本的context

新版本的React context使用了Provider和Customer模式,和react-redux的模式非常像。在頂層的Provider中傳入value,
在子孫級的Consumer中獲取該值,並且能夠傳遞函數,用來修改context,如下代碼所示:

//創建Context組件
const ThemeContext = React.createContext({
  theme: 'dark',
  toggle: () => {}, //向上下文設定一個回調方法
});

//運行APP
class App extends React.Component {
  constructor(props) {
    super(props);

    this.toggle = () => { //設定toggle方法,會作為context參數傳遞
      this.setState(state => ({
        theme:
          state.theme === themes.dark
            ? themes.light
            : themes.dark,
      }));
    };

    this.state = {
      theme: themes.light,
      toggle: this.toggle,
    };
  }

  render() {
    return (
      <ThemeContext.Provider value={this.state}> //state包含了toggle方法
        <Content />
      </ThemeContext.Provider>
    );
  }
}

//中間組件
function Content() {
  return (
    <div>
      <Button />
    </div>
  );
}

//接收組件
function Button() {
  return (
    <ThemeContext.Consumer>
      {({theme, toggle}) => (
        <button
          onClick={toggle} //調用回調
          style={{backgroundColor: theme}}>
          Toggle Theme
        </button>
      )}
    </ThemeContext.Consumer>
  );
}

詳細用法可以參考官方文檔:https://react.docschina.org/docs/context.html#reactcreatecontext

3. context在如下的生命周期鈎子中可以使用

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

4. 在無狀態組件中可以通過參數傳入

function D(props, context) {
  return (
    <div>{this.context.user.name}</div>
  );
}

D.contextTypes = {
  user: React.PropTypes.object.isRequired
}

5. React context的局限性

1. 在組件樹中,如果中間某一個組件 ShouldComponentUpdate returning false 了,會阻礙 context 的正常傳值,導致子組件無法獲取更新。
2. 組件本身 extends React.PureComponent 也會阻礙 context 的更新。

注意點:

1. Context 應該是唯一不可變的
2. 組件只在初始化的時候去獲取 Context

 

參考:https://www.tuicool.com/articles/nUryimf
     https://segmentfault.com/a/1190000012575622


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM