Migrating to the new React Context Api

Source: Internet
Author: User



With the release of React 16.3.0, the context API has also been greatly updated. I have updated from the old version of the API to the new version. Here is a share of my (author) experience.


Review


Here is an example showing how to use the Legacy API:


function Usage(props) {
  return (
    <Toggle onToggle={props.onToggle}>
      <Toggle.On>The button is on</Toggle.On>
      <Toggle.Off>The button is off</Toggle.Off>
      <div>
        <Toggle.Button />
      </div>
    </Toggle>
  )
}


The code above returns a composite componentToggle. This component allows subcomponents to share an implicit state. It can be handled in some simple casesReact.Children.map. However, this example needs to use the context API to achieve the purpose of sharing state with any node of a component tree in React.


The old Context Api


This is an example of a legacy context API application:


 
 
const TOGGLE_CONTEXT = "__toggle__";

// Toggle on
function ToggleOn({ children }, context) {
  const { on } = context[TOGGLE_CONTEXT];
  return on ? children : null;
}

ToggleOn.contextTypes = {
  [TOGGLE_CONTEXT]: PropTypes.object.isRequired
};

// Toggle off
function ToggleOff({ children }, context) {
  const { on } = context[TOGGLE_CONTEXT];
  return on ? null : children;
}

ToggleOff.contextTypes = {
  [TOGGLE_CONTEXT]: PropTypes.object.isRequired
};

// Toggle button
function ToggleButton(props, context) {
  const { on, toggle } = context[TOGGLE_CONTEXT];
  return <Switch on={on} onClick={toggle} {...props} />;
}

ToggleButton.contextTypes = {
  [TOGGLE_CONTEXT]: PropTypes.object.isRequired
};

// Toggle
class Toggle extends React.Component {
  static On = ToggleOn;
  static Off = ToggleOff;
  static Button = ToggleButton;
  static defaultProps = { onToggle: () => {} };
  static childContextTypes = {
    [TOGGLE_CONTEXT]: PropTypes.object.isRequired
  };

  state = { on: false };
  toggle = () =>
    this.setState(
      ({ on }) => ({ on: !on }),
      () => this.props.onToggle(this.state.on)
    );
  getChildContext() {
    return {
      [TOGGLE_CONTEXT]: {
        on: this.state.on,
        toggle: this.toggle,
      }
    };
  }

  render(){
    return <div>{this.props.children</div>
  }
}


In the API, you must specify the state you want to share with a string.getChildContextThe actual context is then returned through the method. Specifies the type of context that is emitted in the parent componentchildContextTypes, which is used in thecontextTypessubassembly to specify the type of context to receive. I (the author, below) never liked such an indirect way, usually also try not to do so. In addition, static properties are used to guarantee that the context value is passed to the subassembly. I don't like it either.



Another problem is that if theshouldComponentUpdatemethod returns False, the value of the context will not change. Of course, this also has a workaround, the specific can refer to this repo.


The new Context API


The new context API doesn't have these problems, which is why I'm so excited. The above example can be updated to:


 
const ToggleContext = React.createContext({
  on:false,
  toggle: () => {},
});

class Toggle extends React.Component {
  static On = ({children}) => (
    <ToggleContext.Consumer>
      {({on})=>(on ? children: null)}
    </ToggleContet.Consumer>
  )

  static Off = ({children}) => (
    <ToggleContext.Consumer>
      {({on}) => (on ? null : children)}
    </ToggleContext.Consumer>
  );

  static Button = props => (
    <ToggleContext.Consumer>
      {({on, toggle}) => (
        <Switch on={on} toggle={toggle} {...props} />
      )}
    </ToggleContext.Consumer>
  )

  toggle = () => this.setState(
    ({on}) => ({on: !on}),
    () => this.props.onToggle(this.state.on)
  );

  state = {on: false, toggle: this.toggle};

  render() {
    return (
      <ToggleContext.Provider value={}>
        {this.props.children}
      </ToggleContext.Provider>
    );
  }
}


The problem with the old API is gone. Now not only does not have the non-direct string, but also has the obvious component:ProviderandConsumerseparately provides and consumes the context.
Each sub-component needs to use the consumer subassembly, just like having a static property in the API. However, this problem with the two API can be solved by a higher-order component based on the render props. Very simple!



AnothershouldComponentUpdateproblem that is updated by returning false is also resolved. The new context API will automatically handle this problem.



The last very good change is that the subcomponents use the render props mode. This can also expose a very elegant interface to the outside world in the new context API.


Issues with the new API


This is the value that is passed in the new APIProviderto the child component, which is changed only when you want the subassembly to be redrawn.
This means that using ' Value={{on:this.state.on, Toggle:this.toggle}} in the Render method is not recommended.
This is because no render will pass in a new object, even if the state itself has not changed.
because it is a new object, all subcomponents are redrawn as well.



This effect will be very large when used in practice. It is generally best to pass in a value that changes only when the state changes. That's whyvalue={this.state}.
If you don't want to pass the entire state to the consumer, then you can use this little Ryan Florence trick.



But there is still a small problem, I need to put thetogglemethod into the state. It's also strange, but it's a minor flaw that doesn't affect the overall situation.


Summarize


The new context API is definitely a very good change for the react team. I hope you can like me as well.



Also: If you can't use this version of 16.3.0, you can add a polyfill to use the new API. This polyfill is create-react-context.



From:https://blog.kentcdodds.com/migrating-to-reacts-new-context-api-b15dc7a31ea0



Migrating to the new React Context Api


Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.