返回博客列表

博客详情

React 设计思维:组合、状态边界与性能意识

用组件思维拆分界面与数据流

约 3 分钟阅读

ReactHooksUI

React 的组件模型让 UI 可以像积木一样拼装,但「怎么拆」会直接影响可读性与性能。本文从组合、状态边界与测量驱动优化三个角度,整理一套在业务代码里反复验证过的思路。

组合优于继承

复用 UI 时,优先用 children、render props 或小型上下文,而不是深继承。把变体留在局部,父组件只负责编排:数据从哪来、子区域如何对齐。这样「上帝组件」不容易出现,改一处也不会牵动整页。

复合组件模式

同一交互域的一组元素(Tabs、Menu)可以用隐式状态或 Context 封装,对外暴露简洁 API。关键是把状态机收敛在内部,外部只传数据与回调。

状态放在哪一层

原则是:能局部就局部,需要共享再提升到最近公共祖先。跨多层级时再用 Context,但要把 Context 拆细:主题、用户会话、功能开关可以分不同 Provider,避免无关更新导致大范围重渲染。

派生状态与副作用

能在渲染中算出来的,不要镜像到 useState 再用 useEffect 同步。副作用要有明确依赖,并避免把不稳定对象(每次 render 新建)放进依赖数组。对复杂异步,可考虑 useReducer 或状态机库,让转移显式化。

性能:先测量再 memo

React.memouseMemouseCallback 能跳过不必要的子树更新,但也会增加阅读成本。我的流程是:先用 Profiler 或真实交互确认卡顿点,再对热点子树加 memo;对列表项、重计算派生值优先。

列表与 key

稳定 key 帮助复用节点;虚拟列表在长列表场景能显著降低 DOM 压力。避免在 render 里创建内联函数传给大量子项,除非已确认需要。

与 Server Components 协同

在 Next.js App Router 中,默认页面是服务端组件:数据与结构尽量留在服务端,客户端组件只包交互与浏览器能力。这样 bundle 更小,也更易保持数据一致性。

边界划分清单

  • 纯展示、可 SEO 的内容 → 服务端。
  • 表单、拖拽、动画、浏览器存储 → 客户端。
  • 需要两者协作时,用 props 把服务端数据注入客户端子树。

可访问性与表单

语义化标签、焦点管理与键盘路径,应在组件设计阶段考虑,而不是事后补 aria。表单校验错误要可读、可恢复,并与后端错误语义对齐。

小结

可维护的 React 代码,本质是清晰的边界与诚实的数据流。组合让变化局部化,状态提升有节制,性能优化跟随测量结果——这套顺序比一上来就堆 memo 更稳。