认识
一、认识
高阶组件 是一个函数,接收一个组件作为参数,返回一个新的组件。高阶组件 一般用于复用逻辑、强化 props
、赋能组件、控制渲染等场景。在使用高阶组件的同时,一般遵循一些约定,如下:
-
不要再
render()
方法中使用高阶组件 -
不要以任何方式改变原始组件
WrappedComponent
-
透传不相关
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
,来强化组件。同样, 高阶组件可以将 HOC
的 state
的配合起来, 抽离 state
, 来控制业务组件的更新。
3.3 赋能组件
赋能组件: 在 wrapComponent
包装组件中, 可以提供一些扩展功能, 比如说额外的生命周期,额外的事件。
3.4 控 制渲染
控制渲染: 在 wrapComponent
包装组件中,可以对原来的组件进行条件渲染、节流渲染、渲染劫持、懒加载等功能。
四、问题
4.1 render 中不要声明 HOC
React
中的Diff
算法(称为协调)使用组件标识来确定它是更新现有子树还是将其丢弃并挂载新子树。如果从render
中返回的组件与前一个渲染中的组件相同(===
),则React
通过将子树与新子树进行区分来递归更新子树。如果他们不相等,则完全卸掉前一个子树。
基于上述所言,如果在Render
中使用HOC
,那么每次调用Render
,HOC
函数都会产生新的组件,这样导致子树每次渲染都会进行卸载和重新挂载的操作。