
本文介绍如何通过函数复用和参数化设计,消除 react 自定义 hook 中高度相似方法的重复代码,提升可维护性与可读性。
在 React 开发中,自定义 Hook 是封装逻辑复用的有力工具。但当多个方法仅在事件类型(如 'ScreenDisplayed' vs 'ScreenCompleted')或上下文常量(如 SCREENS.START)上存在差异时,直接复制粘贴逻辑不仅违反 DRY(Don’t Repeat Yourself)原则,还会增加后续维护成本——例如修改校验逻辑或发布流程时需同步更新多处。
你当前的 useAnalytics Hook 中,fireScreenDisplayed 和 fireScreenCompleted 几乎完全一致,仅差一个事件名称参数。理想方案是提取共用逻辑为单一函数,并通过闭包或参数注入动态行为。以下是两种推荐实践:
✅ 方案一:统一处理器 + 命名导出(推荐)
将核心逻辑封装为一个内联函数,再通过对象属性别名暴露不同语义的方法:
const useAnalytics = (screenType: string) => {
const [done, setDone] = useState(false);
// 共用的核心事件触发逻辑
const fireScreenEvent = (eventType: string, props: Record = {}) => {
_checkScreenValidity();
if (checkDone && done && !props.force) return;
setDone(true);
publishCdmEvent(_buildEvent(eventType, { ...props, screenType }));
};
return {
fireScreenDisplayed: () => fireScreenEvent('ScreenDisplayed'),
fireScreenCompleted: () => fireScreenEvent('ScreenCompleted'),
};
}; 使用方式保持不变:
const { fireScreenDisplayed } = useAnalytics(SCREENS.START);
const { fireScreenCompleted } = useAnalytics(SCREENS.COMPLETED);? 优势:语义清晰、调用简洁、无冗余逻辑;screenType 可作为上下文透传至 _buildEvent,增强事件元数据完整性。
✅ 方案二:高阶工厂函数(适合更复杂场景)
若需支持更多动态配置(如默认 props、拦截器、异步处理),可进一步抽象为工厂函数:
const createFireHandler = (eventType: string, defaultProps: Record= {}) => { return (props: Record = {}) => { _checkScreenValidity(); if (checkDone && done && !props.force) return; setDone(true); publishCdmEvent(_buildEvent(eventType, { ...defaultProps, ...props })); }; }; const useAnalytics = (screenType: string) => { return { fireScreenDisplayed: createFireHandler('ScreenDisplayed', { screenType }), fireScreenCompleted: createFireHandler('ScreenCompleted', { screenType }), }; };
⚠️ 注意事项
- 避免在 Hook 内部直接返回未绑定 this 的箭头函数(本例不涉及类组件,无需担心);
- 确保 _checkScreenValidity、publishCdmEvent 等依赖项在 Hook 作用域内稳定可用(必要时用 useCallback 或 useRef 缓存);
- 若 screenType 影响校验逻辑(如不同页面有不同必填字段),应将其纳入 _checkScreenValidity(screenType) 参数中,实现真正上下文感知。
通过以上重构,你不仅消除了重复代码,还使 Hook 更具扩展性——未来新增 fireScreenSkipped 或 fireScreenError 仅需一行配置,无需复制整段逻辑。这才是 React Hooks “逻辑复用”本质的最佳体现。










