Table of Contents
1. Basic concepts
2. Usage Scenarios
1. Manipulate props
2. Access the component instance through ref
3. Component state improvement
3. Parameter passing
4. Implementation of high-order components through inheritance
Home Web Front-end JS Tutorial What are React advanced components? Detailed explanation of React advanced components

What are React advanced components? Detailed explanation of React advanced components

Sep 14, 2018 pm 01:55 PM
react.js

This article brings you what are the advanced components of React? The detailed explanation of the advanced components of React has certain reference value. Friends in need can refer to it. I hope it will be helpful to you.

1. Basic concepts

Advanced functions are functions that take functions as parameters and return functions. Similarly, higher-order components (HOC for short) receive React components as parameters and return a new React component. A higher-order component is essentially a function, not a component. The function form of high-order components is as follows:

const EnhanceComponent = higherOrderComponent(WrappedComponent)
Copy after login

Explain how high-order components are reused through a simple example. Now there is a component MyComponent that needs to get data from LocalStorage and then render it to the interface. Under normal circumstances, we can implement it like this:

import React, { Component } from 'react'

class MyComponent extends Component {
  componentWillMount() {
    let data = localStorage.getItem('data');
    this.setState({data});
  }
  render() {
    return(
      <div>{this.state.data}</div>
    )
  }
}
Copy after login

The code is very simple, but when other components also need to obtain the same data from LocalStorage and display it, each component needs to rewrite the code in componentWillMount. This is obviously very redundant. Let's take a look at rewriting this part of the code using higher-order components.

import React, { Component } from 'react'

function withPersistentData(WrappedComponent) {
  return class extends Component {
    componentWillMount() {
      let data = localStorage.getItem('data');
      this.setState({data});
    }
    render() {
      // 通过{ ...this.props} 把传递给当前组件属性继续传递给被包装的组件
      return <WrappedComponent data={this.state.data} {...this.props}/>
    }
  }
}

class MyComponent extends Component{
  render() {
    return <p>{this.props.data}</p>
  }
}

const MyComponentWithPersistentData = withPersistentData(MyComponent);
Copy after login

withPersistentData is a high-order component, which returns a new component. In the new component, componentWillMount handles the logic of obtaining data from LocalStorage, and then passes the obtained data to the packaged component through props. WrappedComponent, so that you can directly use this.props.data in WrappedComponent to obtain the data that needs to be displayed. When other components also need this logic, continue to use the high-order component withPersistentData to wrap these components.

2. Usage Scenarios

The usage scenarios of high-order components mainly include the following four:
1) Manipulating props
2) Accessing component instances through ref
3) Component status improvement
4) Wrap components with other elements

1. Manipulate props

Before the wrapped component receives props, higher-order components can intercept props first and add props , delete or modify operations, and then pass the processed props to the wrapped component. The example in 1 belongs to this situation.

2. Access the component instance through ref

The higher-order component ref obtains the reference of the packaged component instance, and then the higher-order component has the ability to directly operate the properties or methods of the packaged component.

import React, { Component } from 'react'

function withRef(wrappedComponent) {
  return class extends Component{
    constructor(props) {
      super(props);
      this.someMethod = this.someMethod.bind(this);
    }

    someMethod() {
      this.wrappedInstance.comeMethodInWrappedComponent();
    }

    render() {
      // 为被包装组件添加 ref 属性,从而获取组件实例并赋值给 this.wrappedInstance
      return <wrappedComponent ref={(instance) => { this.wrappedInstance = instance }} {...this.props}/>
    }
  }
}
Copy after login

When wrappedComponent is rendered, the callback function of ref is executed. The higher-order component saves the wrappedComponent instance reference through this.wrappedInstance, and calls the method in wrappedComponent through this.wrappedInstance in someMethod. This usage is rarely used in actual projects, but it comes in handy when the reuse logic encapsulated by a higher-order component needs to be supported collaboratively by the methods or properties of the packaged component.

3. Component state improvement

Higher-order components can realize the statelessness of packaged components by promoting the state of the packaged component and the corresponding state processing method to the high-order component itself. A typical scenario is to use high-order components to unify the states that originally controlled components need to maintain themselves into high-order components.

import React, { Component } from 'react'

function withRef(wrappedComponent) {
  return class extends Component{
    constructor(props) {
      super(props);
      this.state = {
        value: ''
      }
      this.handleValueChange = this.handleValueChange.bind(this);
    }

    handleValueChange(event) {
      this.this.setState({
        value: event.EventTarget.value
      })
    }

    render() {
      // newProps保存受控组件需要使用的属性和事件处理函数
      const newProps = {
        controlledProps: {
          value: this.state.value,
          onChange: this.handleValueChange
        }
      }
      return <wrappedComponent {...this.props} {...newProps}/>
    }
  }
}
Copy after login

This example upgrades the state used by the value attribute of the controlled component and the callback function that handles value changes to higher-order components. When we use the controlled component again, we can use it like this:

import React, { Component } from 'react'

function withControlledState(wrappedComponent) {
  return class extends Component{
    constructor(props) {
      super(props);
      this.state = {
        value: ''
      }
      this.handleValueChange = this.handleValueChange.bind(this);
    }

    handleValueChange(event) {
      this.this.setState({
        value: event.EventTarget.value
      })
    }

    render() {
      // newProps保存受控组件需要使用的属性和事件处理函数
      const newProps = {
        controlledProps: {
          value: this.state.value,
          onChange: this.handleValueChange
        }
      }
      return <wrappedComponent {...this.props} {...newProps}/>
    }
  }
}


class  SimpleControlledComponent extends React.Component {
  render() {
    // 此时的 SimpleControlledComponent 为无状态组件,状态由高阶组件维护
    return <input name="simple" {...this.props.controlledProps}/>
  }
}

const ComponentWithControlledState = withControlledState(SimpleControlledComponent);
Copy after login

3. Parameter passing

The parameter of a high-order component is not only one component, it can also receive other parameters. For example, in the first example, the data with key data is obtained from LocalStorage. When the key to obtain the data is uncertain, the high-order component withPersistentData does not meet the needs. We can let it receive an additional parameter to decide which data to obtain from LocalStorage:

import React, { Component } from 'react'

function withPersistentData(WrappedComponent, key) {
  return class extends Component {
    componentWillMount() {
      let data = localStorage.getItem(key);
      this.setState({ data });
    }
    render() {
      // 通过{ ...this.props} 把传递给当前组件属性继续传递给被包装的组件
      return <WrappedComponent data={this.state.data} {...this.props} />
    }
  }
}

class MyComponent extends Component {
  render() {
    return <p>{this.props.data}</p>
  }
}
// 获取 key='data' 的数据
const MyComponent1WithPersistentData = withPersistentData(MyComponent, 'data');

// 获取 key='name' 的数据
const MyComponent2WithPersistentData = withPersistentData(MyComponent, 'name');
Copy after login

The new version of withPersistentData meets the need to obtain different key values, but in actual situations, we rarely use this method to pass parameters , but adopts a more flexible and usable function form:

HOC(...params)(WrappedComponent)
Copy after login

The return value of HOC(...params) is a high-order component. The parameters required by the high-order component are passed to the HOC function first. of. Rewrite withPersistentData in this form as follows (Note: This form of high-order component is more concisely defined using arrow functions):

import React, { Component } from 'react'

const withPersistentData = (key) => (WrappedComponent) => {
  return class extends Component {
    componentWillMount() {
      let data = localStorage.getItem(key);
      this.setState({ data });
    }
    render() {
      // 通过{ ...this.props} 把传递给当前组件属性继续传递给被包装的组件
      return <WrappedComponent data={this.state.data} {...this.props} />
    }
  }
}

class MyComponent extends Component {
  render() {
    return <p>{this.props.data}</p>
  }
}
// 获取 key='data' 的数据
const MyComponent1WithPersistentData = withPersistentData('data')(MyComponent);

// 获取 key='name' 的数据
const MyComponent2WithPersistentData = withPersistentData('name')(MyComponent);
Copy after login

4. Implementation of high-order components through inheritance

As introduced earlier The way in which higher-order components are implemented is that the higher-order components process the common logic and then pass the relevant properties to the packaged component. We call this method property proxy. In addition to property proxies, higher-order components can also be implemented through inheritance: logic reuse can be achieved by inheriting packaged components. Higher-order components implemented through inheritance are often used for rendering hijacking. For example, allow the component to render when the user is logged in, otherwise render an empty component. The code is as follows:

function withAuth(WrappedComponent) {
  return class extends WrappedComponent {
    render() {
      if (this.props.loggedIn) {
        return super.render();
      } else {
        return null;
      }
    }
  }
}
Copy after login

Determine whether the user has logged in based on this.props.loggedIn of WrappedComponent. If logged in, call the render method of WrappedComponent through super.render() to render the component normally. Otherwise, return a null. Inheritance method Implementing higher-order components is intrusive to the packaged components. When combining multiple higher-order uses, it is easy for the subclass component to forget to call the parent class component method through super, resulting in logic loss. Therefore, when using higher-order components, you should try to implement them through proxies.

related suggestion:

Super awesome JavaScript React framework introductory tutorial_Basic knowledge

Detailed explanation of MHA parameters of MySQL high availability component

The above is the detailed content of What are React advanced components? Detailed explanation of React advanced components. For more information, please follow other related articles on the PHP Chinese website!

Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn

Hot AI Tools

Undresser.AI Undress

Undresser.AI Undress

AI-powered app for creating realistic nude photos

AI Clothes Remover

AI Clothes Remover

Online AI tool for removing clothes from photos.

Undress AI Tool

Undress AI Tool

Undress images for free

Clothoff.io

Clothoff.io

AI clothes remover

Video Face Swap

Video Face Swap

Swap faces in any video effortlessly with our completely free AI face swap tool!

Hot Tools

Notepad++7.3.1

Notepad++7.3.1

Easy-to-use and free code editor

SublimeText3 Chinese version

SublimeText3 Chinese version

Chinese version, very easy to use

Zend Studio 13.0.1

Zend Studio 13.0.1

Powerful PHP integrated development environment

Dreamweaver CS6

Dreamweaver CS6

Visual web development tools

SublimeText3 Mac version

SublimeText3 Mac version

God-level code editing software (SublimeText3)

How to call the method of child component in React parent component How to call the method of child component in React parent component Dec 27, 2022 pm 07:01 PM

Calling method: 1. Calls in class components can be implemented by using React.createRef(), functional declaration of ref or props custom onRef attribute; 2. Calls in function components and Hook components can be implemented by using useImperativeHandle or forwardRef to throw a child Component ref is implemented.

In-depth understanding of React's custom Hooks In-depth understanding of React's custom Hooks Apr 20, 2023 pm 06:22 PM

React custom Hooks are a way to encapsulate component logic in reusable functions. They provide a way to reuse state logic without writing classes. This article will introduce in detail how to customize encapsulation hooks.

How to debug React source code? Introduction to debugging methods using multiple tools How to debug React source code? Introduction to debugging methods using multiple tools Mar 31, 2023 pm 06:54 PM

How to debug React source code? The following article will talk about how to debug React source code under various tools, and introduce how to debug the real source code of React in contributors, create-react-app, and vite projects. I hope it will be helpful to everyone!

How to set div height in react How to set div height in react Jan 06, 2023 am 10:19 AM

How to set the div height in react: 1. Implement the div height through CSS; 2. Declare an object C in the state and store the style of the change button in the object, then get A and reset the "marginTop" in C. That is Can.

Why React doesn't use Vite as the first choice for building apps Why React doesn't use Vite as the first choice for building apps Feb 03, 2023 pm 06:41 PM

Why doesn’t React use Vite as the first choice for building applications? The following article will talk to you about the reasons why React does not recommend Vite as the default recommendation. I hope it will be helpful to everyone!

7 great and practical React component libraries (shared under pressure) 7 great and practical React component libraries (shared under pressure) Nov 04, 2022 pm 08:00 PM

This article will share with you 7 great and practical React component libraries that are often used in daily development. Come and collect them and try them out!

10 practical tips for writing cleaner React code 10 practical tips for writing cleaner React code Jan 03, 2023 pm 08:18 PM

This article will share with you 10 practical tips for writing simpler React code. I hope it will be helpful to you!

Let's talk about the differences in design and implementation between Vuex and Pinia Let's talk about the differences in design and implementation between Vuex and Pinia Dec 07, 2022 pm 06:24 PM

When developing front-end projects, state management is always an unavoidable topic. The Vue and React frameworks themselves provide some capabilities to solve this problem. However, there are often other considerations when developing large-scale applications, such as the need for more standardized and complete operation logs, time travel capabilities integrated in developer tools, server-side rendering, etc. This article takes the Vue framework as an example to introduce the differences in the design and implementation of the two state management tools, Vuex and Pinia.

See all articles