Home  >  Article  >  Web Front-end  >  What are React advanced components? Detailed explanation of React advanced components

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

不言
不言Original
2018-09-14 13:55:302252browse

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)

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>
    )
  }
}

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);

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}/>
    }
  }
}

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}/>
    }
  }
}

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);

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');

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)

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);

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;
      }
    }
  }
}

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:
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