HOC vs Render Props vs Hooks
相关问题
- 什么是
HOC / Render Props / Hooks
- 为什么需要
HOC / Render Props / Hooks
- 如何提高代码复用性
Hooks
的实现原理- Hooks 相比其他方案有什么优势
关键点
复用性
HOC / Render Props / Hooks
三种写法都可以提高代码的复用性
,但实现方法不同:
- HOC 是对
传入的组件进行增强后,返回新的组件
给开发者; - Render Props 是指将
一个返回 React 组件的函数,作为 prop 传给另一个 React 组件的共享代码的技术
; - Hooks 是
React 提供的一组 API
,使开发者可以在不编写 class 的情况下使用 state 和其他 React 特性
。
知识点深入
-
HOC (Higher Order Component,即高阶组件)
HOC 是React 中复用代码的编程模式
。具体来说,高阶组件是一个纯函数,它接收一个组件并返回一个新的组件
。常见例子:React Redux 的 connect,将 Redux Store 和 React 组件联系起来
。// react-redux connect 例子 const ConnectedMyComponent = connect(mapState)(MyComponent);
// 实现一个简单的 HOC 例子 function logProps(WrappedComponent) { return class extends React.Component { componentDidUpdate(prevProps) { console.log("Current props: ", this.props); console.log("Previous props: ", prevProps); } render() { return <WrappedComponent {...this.props} />; } }; }
-
Render Props
Render Props 是 React 中复用代码的编程模式。主要解决组件逻辑相同而渲染规则不同的复用问题。常见例子:React Router 中,自定义 render 函数,按需使用 routeProps 来渲染业务组件。ReactDOM.render( <Router> <Route path="/home" render={(routeProps) => ( <div>Customize HZFE's {routeProps.location.pathname}</div> )} /> </Router>, node );
-
React Hooks
React Hooks
是 React 16.8 引入的一组 API。开发者可以在不使用 class 写法的情况下,借助 Hooks 在纯函数组件中使用状态和其他 React 功能。function Example() { const [count, setCount] = useState(0); return ( <div> <p>You clicked {count} times</p> <button onClick={() => setCount(count + 1)}>Click me</button> </div> ); }
-
HOC vs Render Props vs Hooks
-
痛点
在实际业务快速迭代过程中,组件常出现大量重复性工作,少量个性化定制的需求,如果不遵循DRY(Don't Repeat Yourself)
的规则,会造成项目臃肿和难以维护的问题。较早的方案是使用HOC / Render Props
进行重构,然而这两种方案都会改变组件层级,容易形成“嵌套地狱”,使得代码的可读性下降。而React Hooks
则很好地解决了这个问题。 -
方案优劣
为辅助理解,可参考以下图片。图中所示为下拉列表功能的三种不同实现,相比于使用一个Class
来书写下拉列表的所有功能,这三种方案都对组件进行了功能拆解,提高了代码的复用性 -
复用性
HOC、Render Props、Hooks 都有提高代码复用性的能力,但根据其设计模式上的差别,适用范围也会有所差异:HOC 基于单一功能原则,对传入组件进行增强;Render Props 复用数据源,按需渲染 UI;Hooks 对于不同场景的复用都有较好的普适性。
-
可读性 / 易用性
-
HOC 可读性差,易用性差
HOC 写法看似简洁,但开发者无法通过阅读 HOC 的调用辨别出方法的作用:看不到接收和返回的结构,增加调试和修复问题的成本;进行多个 HOC 组合使用时,不能确定使用顺序且有命名空间冲突风险,需要了解每个 HOC 的具体实现,难以维护。不建议过度使用 HOC,但比较适合不需要个性化开发定制时使用:常见于第三方库提供 HOC 类型的 API 给开发者进行功能增强。
-
Render Props 可读性较好,易用性强
代码相对冗长,但能清晰看到组件接收的 props 以及传递的功能等,可以对 props 属性重命名,不会有命名冲突。但难以在 render 函数外使用数据源,且容易形成嵌套地狱。
-
Hooks 可读性强,易用性较好
使用 Hooks 时,能清晰看到组件接收的 props 以及传递的功能等,可以对 props 属性重命名,不会有命名冲突,不存在嵌套地狱,且没有数据源获取及使用范围的限制。但 Hooks 编程应遵循函数式编程的实践,否则 Hooks 所需的依赖数组的处理会造成较大的心智负担。