react 高阶组件详解

  • Post author:
  • Post category:其他




1、高阶组件是什么

高阶组件是一个函数,但 参数 和 返回值 为 组件。 高阶组件是包装了另外一个 React 组件的 React 组件、它可以大幅度的简化代码量、使我们更多的去复用代码; 高阶组件可以解决组件冗余的问题,可以使多个组件具有相同或类似的方法。



2、高阶组件用途

1): 最常用之属性代理:

/* eslint-disable*/
import React, { createRef, Component } from 'react';

const firstHoc = (WrappedComponent) => {
  return class extends Component {
    get hocComponent() {
      return this.hocRef.current;
    }

    constructor(props) {
      super(props);
      this.state = {
        userId: '',
      };
      this.logState = this.logState.bind(this);
      this.hocRef = createRef();
    }

    componentWillMount() {
      const userId = localStorage.getItem('userId');
      this.setState({
        userId,
      });
    }

    logState() {
      console.log('==============>', this);
      console.log('====>', this.hocComponent.state);
    }

    render() {
      const { userId } = this.state;
      const hocProps = {
        logState: this.logState,
        userId,
      };
      return <WrappedComponent ref={this.hocRef} {...this.props} {...hocProps} />;
    }
  };
};

class Test extends Component {
  constructor() {
    super();
    this.state = {
      hocTest: '我是hocTest',
    };
  }

  handleView = () => {
    console.log(this.props.userId);
    this.props.logState();
  };

  render() {
    return (
      <div
        onClick={() => {
          this.handleView();
        }}
      >
        Test
      </div>
    );
  }
}

export default firstHoc(Test);



以上例子是导出了 hoc 组件中的 logState 通过 firstHoc 包裹的组件、都可以直接调用 this.props.logState 去打印自身组件的 state 数据

即抽取一些可复用的方法,或属性导出,在子组件内通过 this.porps 访问

2): 抽离 state:

/* eslint-disable max-classes-per-file */
// 普通组件Login
import React, { Component } from 'react';

const formCreate = (WrappedComponent) =>
  class extends Component {
    constructor() {
      super();
      this.state = {
        fields: {},
      };
    }

    changeFiled = (e, key) => {
      const { fields } = this.state;
      fields[key] = e.target.value;
      this.setState({
        fields,
      });
    };

    handleSubmit = () => {
      console.log(this.state.fields);
    };

    render() {
      const props = {
        ...this.props,
        handleSubmit: this.handleSubmit,
        changeFiled: this.changeFiled,
      };
      return <WrappedComponent {...props} />;
    }
  };

class Login extends Component {
  render() {
    return (
      <div>
        <div>
          <label id="username">账户</label>
          <input onChange={(e) => this.props.changeFiled(e, 'username')} />
        </div>
        <div>
          <label id="password">密码</label>
          <input onChange={(e) => this.props.changeFiled(e, 'password')} />
        </div>
        <div onClick={this.props.handleSubmit}>提交</div>
        <div>other content</div>
      </div>
    );
  }
}
export default formCreate(Login);

把子组件中重复功能(如一些简单的受控表单、使用 state 控制输入 value)的状态、及设置 state 抽离在高阶组件中统一管理! 最后在子组件中通过 this.porps.methodsName 获取

3): 统一容器:

const HocTest = (WrappedComponent) =>
  class extends Component {
    render() {
      return (
        <div style={{ background: '#fff' }}>
          头部
          <WrappedComponent {...props} />
          尾部
        </div>
      );
    }
  };

可以在高阶组件中套一层 div 做一些公用样式… 其实还有很多作用

4): 反向继承(渲染劫持):

const withLoading(WrappedComponent) {
    return class extends WrappedComponent {
        render() {
            if(this.props.isLoading) {
                return <Loading />;
            } else {
                return super.render();
            }
        }
    };
}

在 hoc 中直接继承传进来的组件(wrapComponent),在 render 中做一些判断,如是否处于 loading 状态,渲染 loading 或者直接渲染原来内容 super.render();

其实在工作中我们能遇到的使用高阶组件情景很多,就看我们怎么使用;



版权声明:本文为xuewenjie0217原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。