外观
高阶组件解决什么问题?
高阶组件是一个函数,接收组件,返回新组件。用来复用和展示无关的逻辑,例如注入数据、权限或埋点。Hooks 能表达的复用,优先用自定义 Hook,少包一层组件。
原理
jsx
function withUser(Comp) {
return function UserContainer(props) {
const user = useUser()
return <Comp {...props} user={user} />
}
}约定:把其余 props 原样传下去;给返回的组件起 displayName,方便调试;不要在渲染函数里创建高阶组件,那会每次都是新的组件类型,状态被清空。
反向继承(返回的组件 extends 传入的组件)会依赖对方的 render 结构,脆弱,不要用。
Hooks 的问题是逻辑复用要调用 Hook,不能在条件里调用。高阶组件的问题是层级变深、props 来源不清楚。一个权限判断如果只是早返回,用组合:<Can permission="edit">{children}</Can>,比包一层 HOC 更直接。见 权限控制。
追问
和 render props 怎么选?
render props 把渲染函数当参数传进来,数据流看得见,但嵌套深。自定义 Hook 把数据留在调用它的组件里,通常更合适。HOC 还适合在不能改组件内部、只能在外面包一层的时候。
ref 会丢吗?
包一层之后,外面的 ref 指向包装组件,不是原组件。需要往下传时用 forwardRef。React 19 的函数组件可以把 ref 当 prop,包装层仍要自己决定传不传。
易错点
- 多个 HOC 都注入同名 prop,后面的静默覆盖前面的。
- 在 HOC 里复制静态方法却漏了,外部拿不到
getDerivedStateFromProps这类静态成员。 - 为了复用十几行逻辑套三层 HOC,调用栈很难读。