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:

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 注意事项

  1. 不要在渲染函数内创建 HOC(每次渲染创建新组件)
  2. 透传 props:{...props}
  3. 透传 ref:需要 forwardRef
  4. 复制静态方法

同分类其他题目