React useEffect添加函数依赖致非预期执行与eslint警告问题
问题原因
ESLint抛出的react-hooks/exhaustive-deps警告不是误报,警告原文如下:
React Hook useEffect has a missing dependency: 'eventTracker'. Either include it or remove the dependency array.
你遇到的「加了eventTracker依赖后effect启动执行十几次」的问题,本质是两个实现缺陷共同导致的:
- 自定义Hook
useAnalyticsEventTracker每次组件重渲染时,都会返回一个全新创建的eventTracker函数引用,如果直接把它加入useEffect依赖数组,每次重渲染的新函数引用都会被判定为依赖变化,触发effect重复执行。 - 你当前useEffect依赖整个
wallet对象也存在隐患:绝大多数钱包Hook返回的wallet对象会在每次组件重渲染时生成新引用,哪怕内部address值没有实际变化,也会误触发effect。
推荐修复方案
第一步:修复自定义Hook的函数引用稳定性
用useCallback包裹返回的eventTracker函数,保证组件重渲染时只要依赖不变,就返回同一个函数引用:
import ReactGA from 'react-ga'; import { useCallback } from 'react'; const useAnalyticsEventTracker = () => { const eventTracker = useCallback( ( category: string, action: string, label: string, ) => { ReactGA.event({ category, action, label }); }, // ReactGA是全局导入的固定依赖,所以依赖数组传空即可 [] ); return eventTracker; }; export default useAnalyticsEventTracker;
第二步:调整useEffect的依赖项,精准监听目标值
不要依赖整个wallet对象,只监听你实际关心的wallet.address,同时把稳定引用的eventTracker加入依赖数组,既符合ESLint规则,也不会出现重复触发的问题:
const wallet = useWallet(); const eventTracker = useAnalyticsEventTracker(); useEffect(() => { if (wallet?.address) { eventTracker('Wallet', 'Connect', wallet.address); console.log(wallet.address); } }, [wallet?.address, eventTracker]);
不推荐的做法
不要为了消除警告直接加// eslint-disable-next-line react-hooks/exhaustive-deps注释暴力忽略规则,这种写法会让effect长期持有过期的闭包值,后续如果eventTracker内部增加了对组件状态、上下文的依赖,会出现埋点参数错误、逻辑不触发等很难排查的问题。
内容的提问来源于stack exchange,提问作者gameveloster
相关产品推荐
相关产品推荐

