The previous article introduced simple high-level component implementations, followed by high-level components in the form of proxies and inheritance.

High-level components in proxy mode

Application Scenarios:

1. The manipulation of the props

The higher-order component can change the props of the wrapped component, do anything to the props, and even customize events in the higher-order component, which are then passed on through the props. The previous article implemented a simple higher-order component. Here’s how to pass wrapped component properties in higher-order components:

  • App.js
import React from 'react';

import B from './components/B';
import C from './components/C';
import './index.css';

class App extends React.Component {
  render() {
    return(
      <div className="out-box"> {/* here pass the name and age attributes to the B component */} <B name={"Tom"} age={22} />
        <C />
      </div>
    )
  }
}

export default App;
Copy the code
  • A.js
import React, { Component } from 'react';

function hocA(Wrapper) {
  return class A extends Component {
    render() {
      return (
        <div className="box">
          <header className="head"> Header </header> <div className="content">
            <Wrapper />
          </div>
        </div>
      )
    }
  }
};

export default hocA;
Copy the code
  • B.js
import React, { Component } from 'react'; // Import hocA from'./A';

class B extends Component {
  render() {
    return(< div > < div > name: {this. Props. The name} < / div > < div > age: {this. Props. Age} < / div > < div > this is component B < / div > < / div >)}}export default hocA(B);
Copy the code
  • This is the effect of component B

    You can see the B componentpropsYou can’t get what we’re deliveringnameageProperties. The reason is that our properties are passed to the higher-order component A, but our component A does not pass the properties to the wrapped component, so the wrapped component B cannot get themnameageProperties.

  • After the rewriteA.js
import React, { Component } from 'react';

function hocA(Wrapper) {
  return class A extends Component {
    render() {
      return (
        <div className="box">
          <header className="head"> Header </header> <div className="content"> {/* Deconstruct properties passed to higher-order components and pass them to wrapped properties */} <Wrapper {... this.props} /> </div> </div> ) } } };export default hocA;
Copy the code
  • Effect of the page

    How to add attributes to wrapped components from higher-order components

  • A.js
import React, { Component } from 'react';

function hocA(Wrapper) {
  return class A extends Component {
    render() {
      return (
        <div className="box">
          <header className="head"> Header </header> <div className="content"> {/* add sex */} <Wrapper {... this.props} sex={"Male"} />
          </div>
        </div>
      )
    }
  }
};

export default hocA;
Copy the code
  • B component that uses this property,B.js
import React, { Component } from 'react'; // Import hocA from'./A';

class B extends Component {
  render() {
    return(<div> <div> Name :{this.props. Name} </div> <div> Age :{this.props. Age} </div> <div> Gender :{this.props </div> </div> ) } }export default hocA(B);
Copy the code
  • Effect of the page

    How to remove properties of wrapped components from higher-order components

  • After the rewriteA.js
import React, { Component } from 'react';

function hocA(Wrapper) {
  return class A extends Component {
    render() {{/* newProps */ * const {age,... newProps } = this.props;return (
        <div className="box">
          <header className="head"> Header </header> <div className="content"> <Wrapper {... newProps} sex={"Male"} />
          </div>
        </div>
      )
    }
  }
};

export default hocA;
Copy the code
  • Effect of the page
2. Access the ref of the wrapped component
  • A.js
import React, { Component } from 'react';

function hocA(Wrapper) {
  returnClass A extends Component {// instance is passed to the Wrapper Component. }render() {
      return (
        <div className="box">
          <header className="head"> Header </header> <div className="content">
            <Wrapper ref={this.controlRef.bind(this)} />
          </div>
        </div>
      )
    }
  }
};

export default hocA;
Copy the code
  • B.js
import React, { Component } from 'react';
import hocA from './A';

class B extends Component {
  getName() {
    console.log('Visited');
  }
  render() {
    return<div> <div> This is the B component </div> </div>}}export default hocA(B);
Copy the code

At this point we go to the page console and see that the getName method in the wrapped component B is executed.

3. Pull out state

For example, if our higher-order components all have a method in common, such as an input field, and we want that field to be controlled, we need to listen for the input event of that field, and use setState to change the content of the input field each time the value is entered. If we implemented this method ourselves in each component, we would create a lot of duplication. At this point, higher-order components can be used to help us extract the state.

  • A.js
import React, { Component } from 'react';

function hocA(Wrapper) {
  returnclass A extends Component { constructor(props) { super(props); This. state = {value:' 'HandleChange = (e) => {this.setState({value: e.target.value})}render() {
      const newProps = {
        value: this.state.value,
        onChange: this.handleChange
      }
      return (
        <div className="box">
          <header className="head"> Header </header> <div className="content"> {/* Pass status and methods to the wrapped component */} <Wrapper {... newProps} /> </div> </div> ) } } };export default hocA;
Copy the code
  • Copy the code
  • B.js
import React, { Component } from 'react';
import hocA from './A';

class B extends Component {
  render() {
    return<div> {/* Let the higher-order component help us to implement the input box controlled */} <input {... This. Props} /> <div> This is the B component </div> </div>)}}export default hocA(B);
Copy the code
  • C.js
import React, { Component } from 'react';
import hocA from './A'; @hoca class C extends Component {render() {
    return<div> {/* Let the higher-order component help us to implement the input box controlled */} <input {... This. Props} /> <div> This is the C component </div> </div>)}}export default C;
Copy the code
  • Effect of the page

    This allows us to extract common state from higher-order components, improving code reusability.

4. Pack components

Wrapping a component is very simple, and we used this feature earlier. Wrapping a component is adding a series of tags to make the wrapped component look the way it wants.


Second, the inheritance of higher-order components

Components that take inherited associations as arguments and returned components, if the component argument passed in is a Wrapper, then the returned component inherits directly from the Wrapper.

And proxy mode of higher-order components

  • They inherit different classes. Proxy mode higher-order components inherit fromReact.ComponentThe higher-order component inherits from the passed parameter component.
  • renderIn the functionreturnDifferent things go out. The proxy higher-order component returns the passed parameter component, while inheritance returnssuper.render()Render the parameter component.

Application Scenarios:

1. The manipulation of the props

Add properties to the parameter component using an inherited higher-order component

  • A.js
import React from 'react';

function hocA(Wrapper) {
  return class A extends Wrapper {
    renderConst element = super.render(); const element = super.render(); Const newStyle = {// Returns red if the outermost layer of the parameter component element is a div tag, otherwise returns green color: element.type ==='div' ? 'red' : 'green'}; const newProps = { ... this.props, style: newStyle };return (
        <div className="box">
          <header className="head"> Header </header> <div className="content">
            {React.cloneElement(element, newProps, element.props.children)}
          </div>
        </div>
      )
    }
  }
};

export default hocA;
Copy the code
  • B.js
import React, { Component } from 'react';
import hocA from './A';

class B extends Component {
  render() {
    return(<div> this is B component </div>)}}export default hocA(B);
Copy the code
  • C.js
import React, { Component } from 'react';
import hocA from './A'; @hoca class C extends Component {render() {
    return(<span> This is component C </span>)}}export default C;
Copy the code
  • The effect

    In practice, there is no need to use inherited higher-order components to manipulate unless some properties need to be modified judicatively by passing in the parameter componentprops

2. Manipulate lifecycle functions

When the high-order component of inheritance mode needs to modify the life-cycle function, it can directly rewrite the life-cycle function in the high-order component, which will override the life-cycle function of the parameter component.


As can be seen from the above, high-level components in proxy mode are superior to high-level components in inheritance mode, so high-level components in proxy mode are preferred.


Modify the displayed component name

If you open the component debugging tool, you can see that component B and component C have the same name, which is both A. If there are too many components, debugging will be troublesome.

Change the method

Use the Static property displayName in the React class to set the component name to display.

  • A.js
import React, { Component } from 'react';

function hocA(Wrapper) {
  returnClass A extends Component {// sets the displayName of an advanced Component static displayName = 'Box${getDisplayName(Wrapper)}`;
    render() {
      return (
        <div className="box">
          <header className="head"> Header </header> <div className="content">
            <Wrapper />
          </div>
        </div>
      )
    }
  }
};

function getDisplayName(Wrapper) {
  return Wrapper.displayName || Wrapper.name || 'defaultName'
}

export default hocA;
Copy the code
  • The effect