React 组件 业务逻辑编码 最佳实践
当我们强调“组件 Render 阶段必须纯净”时很多刚接触 Hooks 的开发者会产生困惑如果不写在组件函数体里我的业务逻辑到底该往哪放核心的秘密在于我们需要把“业务逻辑”分类。并不是所有业务逻辑都是“副作用”。在 React 中业务逻辑根据其性质有四个完美的去处。业务逻辑的四大分类与去处1. 纯计算逻辑计算衍生状态→\rightarrow→直接写在函数体内如果你的业务逻辑是根据现有的 Props 或 State 计算出一个新数据例如对列表进行搜索过滤、格式化时间、计算总价这属于纯计算没有任何副作用。怎么写直接写在组件函数体内。每次渲染重新计算是完全可接受的如果计算量极大才用useMemo包裹。❌ 错误做法用useEffect监听状态变化然后去setFilteredList这会导致二次渲染。functionProductList({products,filterKeyword}){// ✅ 正确纯计算逻辑直接写在函数体内constfilteredProductsproducts.filter(pp.name.includes(filterKeyword))consttotalPricefilteredProducts.reduce((sum,p)sump.price,0)returndiv总价{totalPrice}/div}2. 用户触发的业务数据提交/修改→\rightarrow→写在事件处理函数或 React 19 Actions 中如果你的业务逻辑是因为用户点了某个按钮、提交了表单才触发的例如删除商品、点赞、提交注册这属于主动意图。怎么写写在onClick、onSubmit等事件回调函数内部或者利用 React 19 的Actions结合useTransition来处理异步提交。特点这些函数只在事件发生时调用绝对不会在 Render 阶段自动执行因此你可以安全地在里面写任何副作用如fetch、修改全局状态。functionDeleteButton({id}){const[isPending,startTransition]useTransition()consthandleDelete(){// ✅ 正确在事件触发的 Action 中编写异步业务逻辑startTransition(async(){awaitfetch(/api/delete/${id},{method:POST})// 更新状态...})}return(button onClick{handleDelete}disabled{isPending}删除/button)}3. 被动同步逻辑依赖外部系统→\rightarrow→写在useEffect或 React 19use()中如果你的业务逻辑是组件一旦加载出来或者某个依赖变了就必须自动去干的一件事例如进入页面自动埋点、根据用户 ID 自动获取详情、订阅 WebSocket。怎么写写在useEffect中或者在 React 19 中使用use(Promise)进行声明式的数据流读取。useEffect((){// ✅ 正确属于被动同步的副作用放在 useEffect 中consttrackernewAnalyticsTracker()tracker.sendPageView()return()tracker.disconnect()// 别忘了清理},[])4. 复杂的跨组件业务→\rightarrow→抽离到自定义 HookCustom Hook中当一个组件里塞满了大量的状态、事件处理、和计算代码变得臃肿时最优雅的解决方案是把业务逻辑彻底抽离出 UI 组件。怎么写创建一个以use开头的自定义 Hook把useState、useEffect、各种计算函数都打包塞进去组件只负责看图说话渲染 UI。// 独立的业务逻辑层 (useCart.js)functionuseCart(){const[items,setItems]useState([])consttotalPriceitems.reduce((sum,i)sumi.price,0)constaddItemitemsetItems([...items,item])return{items,totalPrice,addItem}}// 纯粹的 UI 渲染层 (CartComponent.js)functionCartComponent(){// 组件体内只有一行干净的解构没有任何杂乱的业务逻辑const{items,totalPrice,addItem}useCart()return(button onClick{()addItem({price:10})}加购({totalPrice})/button)}总结速查表业务逻辑类型举例应该写在哪里是否允许副作用衍生数据计算过滤列表、计算总和、格式化文本组件函数体内❌ 绝对不行必须是纯函数用户交互响应点击保存、删除、切换开关事件处理函数 / Actions✅ 可以外部系统同步页面加载取数、监听窗口大小**useEffect/use()**✅ 可以复杂/复用业务完整的购物车逻辑、分页器逻辑自定义 Hooks视内部的具体 Hooks 而定把 UI怎么画和业务怎么算/怎么变通过上述规则清晰地解耦就是写出高质量、可维护 React 19 代码的关键。