React Advanced components

Learn how to React advanced Components of MOOC

What is the React high-order component

A higher-order component takes a component as an argument and returns a new component. A higher-order component is really a function, not just a component.

Second, start Demo to get to know the advanced components

1. Demand analysis

To have a need for:

We split the components in the figure above, which can be divided into external modal prompt box components and internal information components.

The external modal component is constant, but the internal content, we might show different effects in different places. The diagram below.

So we need to wrap an external Modal prompt component, to wrap different internal components.

2. Project construction

// Create an empty project create-react-app XXXCopy the code

Let’s create some new files.

// A/index.js

import React from 'react';
import './index.css';

// Define a function
// Pass in a component as an argument
function A(WrappedComponent) {
  // Return a component
  return class A extends React.Component {
    constructor (props) {
      super(props);
      this.state = {};
    }

    render () {
      return (
        <div className="a-container">
           <div className="header">
             <div className="title">prompt</div>
             <div className="close">X</div>
           </div>
           <div>
             <! -- Use it here -->
             <WrappedComponent />
           </div>
         </div>)}}}// Throw the function
export default A

Copy the code

The A component is our external Modal prompt component. To wrap our internal components.

Let’s implement component B.

// B/index.js

import React from 'react';
import A from '.. /A/index.js';
import './index.css';


class B extends React.Component {
    render() {
        return (
            <div className="wrap">
                <img src="https://raw.githubusercontent.com/freya0608/High-order-component/master/src/imgs/B.png" alt="" />
            </div>); }}<! Call A() to wrap our B component. -->
export default  A(B);

Copy the code

The final result is:

At this point, an entry-level high-level component instance is ok.

Summary: Ways to use higher-order components:

The first is our above method, the second is to use decorators to achieve, the specific configuration you can check online.

Now we have the requirement that the contents of component B may determine the title of component A, so we need to pass the value to A through component B.

// A/index.js

import React from 'react';
import './index.css';

// Here we return an anonymous function that accepts the passed value
export default (title = 'I am the title') = > {// Then returns a function that accepts child components
  return (WrappedComponent) = > {
    // Return our external component
    return class A extends React.Component {
      constructor (props) {
        super(props);
        this.state = {};
      }

      render () {
        return (
          <div className="a-container">
             <div className="header">
               <! -- Here we use the value we passed -->
               <div className="title">{title}</div>
               <div className="close">X</div>
             </div>
             <div>
               <WrappedComponent />
             </div>
           </div>)}}}}Copy the code
// B/index.js
import React from 'react';
import A from '.. /A/index.js';
import './index.css';
class B extends React.Component {
    render() {
        return (
            <div className="wrap">
                <img src="https://raw.githubusercontent.com/freya0608/High-order-component/master/src/imgs/B.png" alt="" />
            </div>); }}<! -- Most of all here -->Export default A(' prompt I ')(B);Copy the code

In this way, we implement B to A component of the value, so that A component can dynamically change some places.

Third, proxy mode of higher-order components

To understand the high-level components of proxy mode, we need to know from prop, access ref, extraction state, package components four parts.

  • props
// A/index

import React from 'react';
import './index.css';

export default (title = 'I am the title') = > {return (WrappedComponent) = > {
    return class A extends React.Component {
      constructor (props) {
        super(props);
        this.state = {};
      }

      render () {
        // [1] First we can get the props passed to the outermost component
        const prop = this.props;
        console.log(prop);

        
        return (
          <div className="a-container">
             <div className="header">
               <div className="title">{title}</div>
               <div className="close">X</div>
             </div>
             <div>
               <! --[2] can be passed to B component -->
               <! --[3] Sex is new -->
               <WrappedComponent sex={'male'} {. this.props} / >
             </div>
           </div>)}}}}Copy the code
// B/index.js

import React from 'react';
import A from '.. /A/index.js';
import './index.css';
class B extends React.Component {
    render() {
        return (
            <div className="wrap">
                <! --[1] Props = props ()My name: {this.props. Name} My gender: {this.props. Sex}<img src="https://raw.githubusercontent.com/freya0608/High-order-component/master/src/imgs/B.png" alt="" />
            </div>); }} export default A(' prompt I ')(B);Copy the code

In the APP we can set props, pass it to component A, which filters or adds props, and then pass it to COMPONENT B, so that B can receive the outermost layer and the props passed from component A. Also, as A is the middle layer, A has the authority to control which props B can get and can add some additional attributes.

<B name={'zjj'}></B>
Copy the code
  • refs
// A/index

import React from 'react';
import './index.css';

export default (title = 'I am the title') = > {return (WrappedComponent) = > {
    return class A extends React.Component {
      constructor (props) {
        super(props);
        this.state = {};
      }
      [1] Defines a click event
      handleClick = (a)= > {
        this.wref.getName();
      }


      render () {
        const prop = this.props;
        console.log(prop);
        return (
          <div className="a-container">
             <div className="header">
               <div className="title">{title}</div>
               <div className="close">X</div>
             </div>
             <div>
                <! -- [2] bind ref -->
               <WrappedComponent ref={ (v) = >This. wref = v} sex={' male '} {... this.props} /></div>
             <div>
             <! -- [3] Click the event trigger -->
              <button onClick={this.handleClick}>Get the name</button>
             </div>
           </div>)}}}}Copy the code

Let’s define a getName method in B. So by clicking on the button in A, you can call

B/index

getName = (a)= > {
  console.log('获取到了name')}Copy the code
  • Extraction of state
// A.js
import React from 'react';
import './index.css';

export default (title = 'I am the title') = > {return (WrappedComponent) = > {
    return class A extends React.Component {
      constructor (props) {
        super(props);
        this.state = {
          value: ' '
        };
      }

      / / click
      handleClick = (a)= > {
        this.wref.getName();
      }

      // [1] Sets val based on the input
      handleOnInputChange = (e) = > {
        this.setState({
          value: e.target.value
        })
      }

      render () {
        const prop = this.props;
        console.log(prop);
        
        // [2] Set new props
        var newProps = {
          value: this.state.value, / / the incoming values
          onInput: this.handleOnInputChange // Listen for input to the form
        }
        return (
          <div className="a-container">
             <div className="header">
               <div className="title">{title}</div>
               <div className="close">X</div>
             </div>
             <div>
               <WrappedComponent ref={ (v) = >This. wref = v} sex={' male '} {... this.props} {... NewProps} /> // [3] Pass in child components</div>
             <div>
              <button onClick={this.handleClick}>Get the name</button>
             </div>
           </div>)}}}}Copy the code
// B/index.js // use the values passed in, so that the implementation of the child component can be extracted and put into a common component, unified management <inputtype="text" value={this.props.value} onInput={this.props.onInput} />
Copy the code
  • Packaging components

In fact, we have implemented the effect of wrapping the internal components above.