1. 前言
前面咱们一起学了好多常用的 React 设计模式常用React设计模式(上)、常用设计模式下,今天咱们就来聊聊这些设计模式在开发中的·最佳用法,还有得避开的一些常见坑。
2. 最佳实践
2.1 组件创建
在React框架中,我们推荐使用函数式组件结合Hooks模式进行开发。Hooks机制能够有效简化状态管理和副作用的处理流程,进而提升组件的可读性和可测试性。相较于类组件,函数式组件避免了复杂的生命周期方法和this绑定问题,从而显著降低了开发过程中的错误率。
使用函数组件方式
- 简洁易读:无需类语法,无需 render 函数
- 性能更好:没有生命周期方式的开销
- 支持 Hook: 状态和副作用管理更灵活
- 完全替换 class:状态管理、副作用处理、数据获取、表单、定时器、动画、访问浏览器 API、复杂逻辑封装等
- 公共逻辑方便抽离复用:
-
- 比如 useFetchData、useScrollPosition、useClickoutSide等自定义 hook
- 管理状态和副作用使用清晰方便:
-
- useState 和 useEffect 轻松管理状态和副作用。
- 性能更忧:
-
- 可使用 useMemo 和 useCallback 优化性能
2.2 组件拆分
拆分复杂组件是提升代码质量和维护性的关键。遵循单一职责原则,让每个组件负责一个功能,提高可读性和复用性。
2.3 组件逻辑复用
在React框架中,实现组件逻辑的复用是提升开发效率的一项重要策略。下面分别展示三个相关示例。
2.4 组件传参
在React框架中,组件间的参数传递主要通过Props实现,这是父组件向子组件传输数据和行为的主要机制。
3. 一些模式常见陷阱
3.1 Hooks 模式
滥用 useEffect
- 盲目使用 useEffect 监听状态,导致依赖触发更新混乱,区分主动触发与被动触发
- 只有当代码应该在组件被展示给用户再运行时,才应该使用 useEffect
依赖数组管理不当
- 闭包问题,更新依赖、使用 useRef 保存每次渲染的值,用到的时候从 ref.current。
3.2 容器组件与展示组件模式
职责混乱
- 尽量避免展示组件管理状态或处理数据逻辑
过度分离
- 组件数量膨胀,增加代码的复杂性,不要为分离而分离。小型或简单组件可以直接管理状态
性能问题
- 避免容器组件逻辑太多,采用性能优化 api
3.2 组件的受控与非受控模式
状态与 UI 不同步
- 没有及时更新状态
非受控组件的状态难以管理
- 比如下单页面业务组件没有做好受控封装,会导致添加持久化、再来一单功能越发困难。
性能问题
- 在受控组件中,每次输入变化都会触发状态更新和重新渲染
- 使用 React.memo 优化渲染,或在合适情况下切换到非受控组件以减少不必要的状态更新
3.3 提供者模式
常见问题
- Context 重渲染问题
- 深层嵌套的 Provider
解决方案
- 精简 Context 使用范围
-
- 需要共享的状态才放到状态管理处,也避免存储复杂的数据结构,导致性能问题
- 拆分 context,不同 context 保持独立更新
- 合理选择 Provider 层级
-
- 尽量放置靠近需要共享的地方
- 避免过度依赖 Context,简单的通过 prop 处理
总结
熟练掌握与组件创建、拆分、逻辑复用以及参数传递相关的设计模式,以提升代码复用性和可维护性。同时,需规避 Hooks 依赖关系不明确、Context 频繁更新等常见陷阱,以优化系统性能并提升开发体验。
现在我们再次审视React中的设计模式,在选择恰当的设计模式时,应当依据项目的规模大小、复杂程度以及实际需求来进行决策。
- 创建组件
-
- 容器组件与展示组件模式建议常用,但注意不要过度拆分
- 组合模式,页面布局、父子组件联动(Form与Form.Item、Tab与Tab.Panel)
- Hooks 模式赋予函数组件强大能力,管理状态和副作用
- 组件逻辑复用
-
- 高阶组件模式
- render Props
- 自定义 Hook(优先)
- 组件数据获取、状态管理
-
-
提供者模式、单向数据流与组件受控与非受控状态控制
-
看共享状态复杂、多少、频率使用 Context,或者状态库 Redux、Mobox 、Zustand,保证状态管理的可预测性和一致性。
-
最后留个大家一个思考问题,“React 和 Vue 中的设计模式区别与联系是什么”
共勉:
- “软件系统必须随着需求的变化而演进,设计模式帮助我们应对这些变化。”——佚名“设计模式是开发者之间沟通的桥梁,使得复杂系统变得更容易理解。”——佚名
- “StayHungry,Stay Foolish”—— Steve Jobs
推荐书籍:
- 《设计模式:可复用面向对象软件的基础》
- 《JavaScript 设计模式与开发实践》
- 《重构-改善既有代码的设计》