React 高阶组件(HOC)和 render props 模式是什么?
高阶组件(HOC)
HOC 是一个函数,接收组件返回新组件,用于逻辑复用。
// HOC 示例:添加 loading 状态
function withLoading(WrappedComponent) {
return function WithLoading({ isLoading, ...props }) {
if (isLoading) return <Spinner />
return <WrappedComponent {...props} />
}
}
// 使用
const UserList = withLoading(UserListComponent)
<UserList isLoading={true} />常见 HOC:
withRouter(React Router)connect(Redux)withStyles(Material UI)
Render Props
通过 prop 传递渲染函数,实现逻辑复用。
// Render Props 组件
function MouseTracker({ render }) {
const [pos, setPos] = useState({ x: 0, y: 0 })
return (
<div onMouseMove={e => setPos({ x: e.clientX, y: e.clientY })}>
{render(pos)}
</div>
)
}
// 使用
<MouseTracker render={({ x, y }) => (
<div>Mouse at {x}, {y}</div>
)} />Hooks 时代的替代方案
React Hooks 出现后,大多数 HOC 和 render props 可以用自定义 Hook 替代:
// 自定义 Hook
function useMousePosition() {
const [pos, setPos] = useState({ x: 0, y: 0 })
useEffect(() => {
const handler = e => setPos({ x: e.clientX, y: e.clientY })
window.addEventListener('mousemove', handler)
return () => window.removeEventListener('mousemove', handler)
}, [])
return pos
}
// 使用
function Component() {
const { x, y } = useMousePosition()
return <div>Mouse at {x}, {y}</div>
}对比
| 方案 | 优点 | 缺点 |
|---|---|---|
| HOC | 可组合 | 嵌套地狱、props 冲突、ref 传递问题 |
| Render Props | 灵活、清晰 | 回调地狱 |
| Hooks | 简洁、组合自由 | 不能用于 class 组件 |
HOC 注意事项
- 不要在渲染函数内创建 HOC(每次渲染创建新组件)
- 透传 props:
{...props} - 透传 ref:需要
forwardRef - 复制静态方法