# React Context

# 介绍

# 注意事项

在React的官网文档里面提到了一个一个注意事项 caveats (opens new window)

不建议通过如下的方式书写,会带来一些问题,那会有哪些问题呢?

class App extends React.Component {
  render() {
    return (
      <Provider value={{something: 'something'}}>
        <Toolbar />
      </Provider>
    );
  }
}

举例来说

import React, { useState } from 'react';

// class Toolbar extends React.PureComponent {
class Toolbar extends React.Component {

  shouldComponentUpdate(nextProps, nextState, nextContext) {
    //shallow compare will failed here and cause a render.
    if(this.props.value !== nextProps.value) {
      return true
    }
    return false;
  }

  render() {
    console.log('render Toolbar');
    return (
      <div>
        I am Toolbar
      </div>
    )
  }
}

// const ThemeContext = React.createContext('light');

class Child extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      value: { something: 'something' },
    };
  }

  render() {
    console.log('render Child');
    return (
      /*<Toolbar value={ {value: this.state.value} }/>  use this line you will see see LOG: `render Toolbar`*/
      <Toolbar value={ this.state.value }/>
    );
  }
}

function App() {
  const [value, SetValue] = useState(0)

  const onClick = () => {
    SetValue(value + 1)
  };

  return (
    <div>
      <Child/>
      <button onClick={ onClick }>{ value }</button>
    </div>
  );
}

export default App;

如果按照每次都是生成新的{}那么通过shouldComponent(自己实现,仅简单比较Props,和或者PureComponent原理一样)或者PureComponent来进行比较时就会失败,造成不必要的一次渲染。

使用Context也是类似的

import React, { useState } from 'react';

// class Toolbar extends React.PureComponent {
class Toolbar extends React.Component {

  shouldComponentUpdate(nextProps, nextState, nextContext) {
    if(this.props.value !== nextProps.value) {
      return true
    }
    return false;
  }

  render() {
    console.log('render Toolbar');
    return (
      <div>
        I am Toolbar
      </div>
    )
  }
}

class Child extends React.PureComponent {

  render() {
    console.log('render Child');

    return <ThemeContext.Consumer>
      { value => <Toolbar value={ value }/> }
    </ThemeContext.Consumer>
  }
}

class Parent extends React.Component {
  constructor() {
    super();
    this.state = {
      value: {
        name: 'name'
      }
    }
  }

  render() {
    return (
      /*<ThemeContext.Provider value={ { name: 'name'} }>*/ // <== you will see LOG: `render Toolbar`
      <ThemeContext.Provider value={ this.state.value }>
        <Child/>
      </ThemeContext.Provider>
    )
  }
}

const ThemeContext = React.createContext('');

function App() {
  const [value, SetValue] = useState(0);

  const onClick = () => {
    SetValue(value + 1)
  };

  return (
    <div>
      <button onClick={ onClick }>{ value }</button>
      <Parent/>
    </div>
  );
}

export default App;
陕ICP备20004732号-3