HOC 高阶组件

133 阅读1分钟

HOC : higher order component

HOC是一个纯函数,没有副作用

HOC是参数为组件,返回值为新组件的函数。组件是将props转换为UI,而高阶组件是将组件转换为另一个组件,但是不修改原组件。

例如:入参是一个组件,出参也是一个组件

function(componentA){
  return componentB
}

作用:

  1. 抽离重复代码,实现组件的复用
  2. 条件渲染,渲染拦截
  3. 拦截组件的生命周期

利用HOC进行属性代码修改

  1. 修改参数,props
function HOC(WrappedComponent) {
  const newProps = { type: "HOC" };
  return props => <WrappedComponent {...props} {...newProps} />;
}

class类的写法

function HOC(WrappedComponent) {
  return class extends React.Component {
    render() {
      const newProps = { type: "HOC" };
      return <WrappedComponent {...this.props} {...newProps} />;
    }
  };
}
  1. 修改state
function HOC(WrappedComponent) {
  return class extends React.Component {
    constructor(props) {
      super(props);
      this.state = {
        name: "",
      };
      this.onChange = this.onChange.bind(this);
    }

    onChange = (e) => {
      this.setState({
        name: e.target.value,
      });
    };

    render() {
      const newProps = {
        name: this.state.name,
        onChange: this.onChange,
      };
      return <WrappedComponent {...this.props} {...newProps} />;
    }
  };
}
class Example extends React.Component{
  render() {
      return <input name {...this.props.name} />
  }
}
  1. 条件渲染
function HOC(WrappedComponent) {
   return props =>
   props.isShow ? WrappedComponent : <div>empty</div>;
}
  1. 外部逻辑的封装
function HOC(WrappedComponent) {
  return (
    <div>
      <p>Study</p>
      <WrappedComponent></WrappedComponent>
    </div>
  );
}

反向继承

function HOC(WrappedComponent) {
  return class extends WrappedComponent{
    render(){
      return super.render()
    }
  };
}
  1. 可以访问到props state
  2. 实现所谓生命周期的拦截
function HOC(WrappedComponent) {
  const didMount = WrappedComponent.prototype.componentDidMount;
  return class extends WrappedComponent{
    async componentDidMount(){
      if(didMount){
        await didMount.apply(this)
      }
    }
    render(){
      return super.render()
    }
  };
}
  1. 进行修改react树
function HOC(WrappedComponent) {
  return class extends WrappedComponent{
    render(){
      const tree = super.render()
      const newProps = {}

      if(tree && tree.type === "input"){
        newProps.value = "inputTest"
      }

      const props = {
        ...tree.props,
        ...newProps
      }

      const newTree = React.cloneElement(tree, props, tree.props.children)
      return newTree
    }
  };
}
  1. 计算组件的渲染时间
function withTiming(WrappedComponent) {
  let start,end
  return class extends WrappedComponent{
   constructor(props) {
     super(props)
     start = new Date().getTime()
   }
   componentDidMount(){
    if(super.componentDidMount){
      super.componentDidMount()
    }
     end = new Date().getTime()
     console.log(end-start)
   }
  };
}

属性代理和反向继承对比

  • 属性代理:外 --> 内,传递props
  • 反向继承:内 --> 外,render、props、state