useEffect仅依赖appStateVisible、忽略exhaustive-deps提示是否合理?
结论
你当前的场景下直接禁用exhaustive-deps规则是合理的,但也存在不需要禁用规则的更稳妥实现方案。
合理性说明
你的业务触发条件非常明确:仅当应用切至后台/ inactive状态时才执行批量数据上报,不需要在views、user等数据更新时触发上报逻辑。如果强行将这些变量加入依赖数组,反而会导致不符合预期的多次上报,所以如果追求实现简洁,直接在依赖数组上方加// eslint-disable-next-line react-hooks/exhaustive-deps注释禁用规则是完全可行的,只要你确认上报时取到的变量值符合预期即可。
更优实现方案(无需禁用规则)
如果希望完全遵循Hook规则,避免禁用注释带来的潜在维护风险,可以通过以下两种方案实现:
方案1:用useRef存储非触发依赖
用Ref同步不需要触发effect的变量,effect内仅读取Ref的current值,这样既可以保证取到最新值,也不会触发eslint警告:
// 定义Ref存储非触发依赖 const viewsRef = useRef(views); const userRef = useRef(user); const cancelTokenRef = useRef(cancelToken); // 变量更新时同步到Ref useEffect(() => { viewsRef.current = views; userRef.current = user; cancelTokenRef.current = cancelToken; }, [views, user, cancelToken]); // 业务逻辑effect useEffect(() => { async function handleViews() { await sendViews(viewsRef.current, userRef.current, cancelTokenRef.current); // 其余逻辑 } if ( appStateVisible.match('inactive') || appStateVisible.match('background') ) { handleViews(); } }, [appStateVisible]);
方案2:React 18+ 用useEvent封装逻辑
React 18提供的useEvent原生就是为了解决这类“effect中需要读取最新状态但不希望状态变更触发effect执行”的场景,代码更简洁:
// 封装后台上报逻辑 const handleBackgroundReport = useEvent(async () => { await sendViews(views, user, cancelToken); // 其余逻辑 }); useEffect(() => { if ( appStateVisible.match('inactive') || appStateVisible.match('background') ) { handleBackgroundReport(); } }, [appStateVisible, handleBackgroundReport]);
内容的提问来源于stack exchange,提问作者Daniel Shen
相关产品推荐
相关产品推荐

