跳到主要内容

认识

一、认识


高阶组件 是一个函数,接收一个组件作为参数,返回一个新的组件。高阶组件 一般用于复用逻辑强化 props赋能组件控制渲染等场景。在使用高阶组件的同时,一般遵循一些约定,如下:

  1. 不要再 render() 方法中使用高阶组件

  2. 不要以任何方式改变原始组件 WrappedComponent

  3. 透传不相关 props 属性给被包裹的组件 WrappedComponent

二、语法


2.1 基础定义

import React, {Component, ComponentType} from 'react';

function WithHoc<K, T>(WrappedComponent: ComponentType<K>, argu: T) {
return class extends Component {
constructor(props: K) {
super(props);
this.state = {};
}

render(): React.ReactNode {
return <WrappedComponent {...(this.props as K)} />;
}
};
}

export default WithHoc;

2.2 跨层级捕获 ref

高阶组件的约定是将所有 props 传递给被包装组件,但这对于 refs 并不适用。那是因为 ref 实际上并不是一个 prop - 就像 key 一样,它是由 React 专门处理的。如果将 ref 添加到 HOC 的返回组件中,则 ref 引用指向容器组件,而不是被包装组件。我们可以通过 forwardRef 来解决这个问题。

import React, {Component, ComponentType} from 'react';

function WithHoc<K, T>(WrappedComponent: ComponentType<K>, argu: T) {
class WrapComponent extends Component {
constructor(props: K) {
super(props);
this.state = {};
}

render(): React.ReactNode {
const { forwardedRef ,...otherProps } = this.props
return <WrappedComponent ref={forwardedRef} {...(otherProps as K)} />;
}
}

return React.forwardRef((props,ref)=> <WrapComponent forwardedRef={ref} {...props} /> )
}

export default WithHoc;

三、用法


3.1 复用逻辑

复用逻辑: 高阶组件更像是一个加工 react 组件的工厂,批量对原有组件进行加工,包装处理。我们可以根据业务需求定制化专属的 HOC,这样可以解决复用逻辑。

3.2 强化 props

强化 props: 这个是高阶组件最常用的功能,承接上层的 props,在混入自己的 props,来强化组件。同样, 高阶组件可以将 HOCstate 的配合起来, 抽离 state, 来控制业务组件的更新。

3.3 赋能组件

赋能组件: 在 wrapComponent 包装组件中, 可以提供一些扩展功能, 比如说额外的生命周期,额外的事件。

3.4 控制渲染

控制渲染: 在 wrapComponent 包装组件中,可以对原来的组件进行条件渲染节流渲染渲染劫持懒加载等功能。

四、问题


4.1 render 中不要声明 HOC

React中的Diff算法(称为协调)使用组件标识来确定它是更新现有子树还是将其丢弃并挂载新子树。如果从render中返回的组件与前一个渲染中的组件相同(===),则React通过将子树与新子树进行区分来递归更新子树。如果他们不相等,则完全卸掉前一个子树。

基于上述所言,如果在Render中使用HOC,那么每次调用RenderHOC函数都会产生新的组件,这样导致子树每次渲染都会进行卸载和重新挂载的操作。