HOC 与 Render Props
React 中两种代码复用模式的区别与使用场景
问题
React 高阶组件 (HOC) 与 Render Props 的区别与应用。
解答
高阶组件 (HOC)
HOC 是一个函数,接收组件作为参数,返回增强后的新组件。
// 创建一个添加鼠标位置追踪功能的 HOC
function withMouse(WrappedComponent) {
return class extends React.Component {
state = { x: 0, y: 0 };
handleMouseMove = (e) => {
this.setState({ x: e.clientX, y: e.clientY });
};
componentDidMount() {
window.addEventListener('mousemove', this.handleMouseMove);
}
componentWillUnmount() {
window.removeEventListener('mousemove', this.handleMouseMove);
}
render() {
// 将鼠标位置作为 props 传递给被包裹组件
return <WrappedComponent {...this.props} mouse={this.state} />;
}
};
}
// 使用 HOC
function DisplayPosition({ mouse }) {
return (
<p>
鼠标位置: ({mouse.x}, {mouse.y})
</p>
);
}
const EnhancedDisplay = withMouse(DisplayPosition);
Render Props
Render Props 是通过 props 传递一个渲染函数,让组件知道如何渲染内容。
// 创建一个提供鼠标位置的组件
class Mouse extends React.Component {
state = { x: 0, y: 0 };
handleMouseMove = (e) => {
this.setState({ x: e.clientX, y: e.clientY });
};
componentDidMount() {
window.addEventListener('mousemove', this.handleMouseMove);
}
componentWillUnmount() {
window.removeEventListener('mousemove', this.handleMouseMove);
}
render() {
// 调用 render prop 函数,传入当前状态
return this.props.render(this.state);
}
}
// 使用 Render Props
function App() {
return (
<Mouse
render={({ x, y }) => (
<p>
鼠标位置: ({x}, {y})
</p>
)}
/>
);
}
使用 children 作为函数
Render Props 的变体,更简洁:
class Mouse extends React.Component {
state = { x: 0, y: 0 };
// ... 同上
render() {
return this.props.children(this.state);
}
}
// 使用
function App() {
return (
<Mouse>
{({ x, y }) => (
<p>
鼠标位置: ({x}, {y})
</p>
)}
</Mouse>
);
}
对比
| 特性 | HOC | Render Props |
|---|---|---|
| 使用方式 | 函数包裹组件 | 组件内传递渲染函数 |
| Props 来源 | 隐式注入 | 显式传递 |
| 组合多个功能 | 嵌套调用 | 嵌套组件 |
| 静态组合 | ✅ 编译时确定 | ❌ 运行时确定 |
| 调试体验 | 组件层级深 | 相对清晰 |
现代替代方案:Hooks
// 自定义 Hook 实现相同功能
function useMouse() {
const [position, setPosition] = useState({ x: 0, y: 0 });
useEffect(() => {
const handleMove = (e) => {
setPosition({ x: e.clientX, y: e.clientY });
};
window.addEventListener('mousemove', handleMove);
return () => window.removeEventListener('mousemove', handleMove);
}, []);
return position;
}
// 使用
function App() {
const { x, y } = useMouse();
return (
<p>
鼠标位置: ({x}, {y})
</p>
);
}
关键点
- HOC 是函数,接收组件返回新组件;Render Props 是通过 props 传递渲染函数
- HOC 的 props 是隐式注入的,可能产生命名冲突;Render Props 显式传递,更清晰
- HOC 适合静态增强,Render Props 适合动态渲染逻辑
- 多个 HOC 嵌套会形成”包装地狱”,调试困难
- 现代 React 推荐使用 Hooks 替代这两种模式,更简洁且无嵌套问题
目录