@[toc]

React High-level component HOC

I. Definition (What is a higher-order component)

First, high-order component is a framework technology of “state logic reuse”. The commonly used ones in React mainly include mixin, Hoc and hooks.

What is a higher-order Component? A React Component wraps HOC (Higher Order Component) around another React Component by adding logic to an existing Component class through functions.

Higher-order components are special higher-order functions (a class is essentially a function, and a component is a function). A higher-order component receives a component function and returns a new component function. The concept of higher-order functions comes from JavaScript higher-order functions: a higher-order function is a function that takes a function as input or output

Ii. Usage scenarios (what is the use of higher-order components)

1. Code reuse and code modularization

If the functionality is for multiple components, and each component has the same set of code, it’s obviously not wise to use HOC.

  • For example. Add props popovers for each page
function withPopupComponent(C) { return class extends React.Component { constructor(props) { super(props); this.state = { popup: null, modal: null, modalVisible: false, bgStyle: {}, onRequestClose: null, }; } componentDidMount() { } componentWillUnmount() { this.setState({ pop: null, modal: null, modalVisible: false }) } modal = (modal, bgStyle = {}, isBgTouch, onRequestClose) => { this.setState({ modal: modal, modalVisible: React.isValidElement(modal), bgStyle, isBgTouch: !! isBgTouch, onRequestClose: onRequestClose, }) }; popup = (popup = null, popContainerStyle = {}) => { if (_.contains(Const.androidFinishPage, global.curRouteName)) { eventEmitterUtils.activateCallBack('HiddenTabBarKey', { hidden: React.isValidElement(popup) }); } this.setState({ popup: popup, popContainerStyle, }) }; render() { const { modalVisible, modal, bgStyle, isBgTouch, onRequestClose, popup, popContainerStyle } = this.state; return ( <View style={{ flex: 1 }}> <C modal={this.modal} popup={this.popup} {... this.props} /> <ModalView modalVisible={modalVisible} bgStyle={bgStyle} isBgTouch={isBgTouch} onRequestClose={() => { if  (onRequestClose) { onRequestClose() } else { this.setState({ modalVisible: false, modal: null, onRequestClose: null, }) } }}> {modal} </ModalView> { React.isValidElement(popup) ? <Popup popup={popup} style={popContainerStyle} /> : null } </View> ) } } }Copy the code
2, add, delete and change props

You want to add props to the wrappedComponent, so consider using HOC.

  • For example. Add a props to the wrappedComponent
function control(wrappedComponent) { return class Control extends React.Component { render(){ let props = { ... this.props, message: "You are under control" }; return <wrappedComponent {... props} /> } } }Copy the code
3. Render hijacking

The rendering hijack here is not that you can control the details of how it renders, but whether or not it renders. Because the details are controlled by the Render method inside the component, you have no control over the render details.

For example, a component can realistically load… Does not display the specific contents of the component. Or page permission management

  • For example. The component must load the data before it finishes loading.
function loading(wrappedComponent) { return class Loading extends React.Component { render(){ if(! this.props.data) { return <div>loading... </div> } return <wrappedComponent {... props} /> } } }Copy the code

Three, writing (two ways of implementation, three ways of writing)

3.1 Props Proxy (PP- Attribute Proxy)

Type1 PP- Property broker JSX component writing

/** * Const HOC1 = (WrappedComponent) => Class WarppedComponent extends Component {render() {const HOC1 = (WrappedComponent) => Class WarppedComponent extends Component {render() { return ( <View style={styles.container}> <WrappedComponent {... This. Props} /> <TouchableOpacity style={styles.button}> <Text style={styles. Text}> Type1 :PPHOC </TouchableOpacity> </View> ) } }Copy the code

Type2 PP- Property proxy JS functional writing

/** * const HOC2 = (WrappedComponent) => {const targetRender = WrappedComponent.prototype.render; return WrappedComponent.prototype.render = function () { return (<View style={styles.container}> { targetRender.call(this) } <TouchableOpacity style={styles.button}> <Text Style ={styles.text}>type2:PPHOC Props </ text > </TouchableOpacity> </View>); }; }Copy the code
3.2 Inheritance Inversion (II- Reverse Inheritance)

Type3 Inheritance Inversion (II- Reverse Inheritance)

/** * Type3 Inheritance Inversion (II- Reverse Inheritance) */ const HOC = (WrappedComponent) => class extends WrappedComponent { render() { return ( <View style={styles.container}> {super.render()} <TouchableOpacity style={styles.button}> <Text Style ={styles.text}>type3:IIHOC Props </ text > </TouchableOpacity> </View>); }}Copy the code

Base class or higher-order component choice

  • Advantages of base classes

    • 1. Subclasses can easily reuse the methods of their parent class
  • Disadvantages of base classes

    • 1. Inheritance means that subclasses have undifferentiated parent methods, which can pollute subclass code
    • In React, the parent class controls the page rendering logic of the subclass, causing the life cycle of the subclass to be out of order and unable to use the original life cycle methods.

    HOC is also officially recommended over base classes

5. HOC example

5.1 Use of React-Navigation

Refer to “the react – the navigation” : “3.6.1 track”/node_modules/react – navigation tabs/dist/views/BottomTabBar js

5.2 react official website Example

This is an example from the official website that can be used to monitor changes to props passed by a parent component

function logProps(InputComponent) {
  InputComponent.prototype.componentDidUpdate = function(prevProps) {
    console.log('Current props: ', this.props);
    console.log('Previous props: ', prevProps);
  };
  // The fact that we're returning the original input is a hint that it has
  // been mutated.
  return InputComponent;
}

// EnhancedComponent will log whenever props are received
const EnhancedComponent = logProps(InputComponent);
Copy the code

What should we pay attention to when using HOC

6.1. Try not to arbitrarily modify the props needed by child components

This is because modifying the props passed from the parent to the child is risky and may cause errors in the child component. For example, if a props of name was needed, but it was deleted in HOC, the sub-components might not render properly or even report errors.

6.2. Fast Refresh will lose hoc’s new method

This error is caused by hot hot loading Fast Refresh loading only the page and not hoc when the page is dynamically updated. Processing method is 1, the use of hot reload without the use of Fast Refresh to 2, or modify/node_modules/react/CJS/react. Development. Js increase necessary method, as shown in figure