React useEffect依赖项警告差异:为何prop.func触发警告而prop.value不触发?
为什么会出现差异?
1. prop.value无警告的原因
prop.value是原始值类型(字符串、数字、布尔等),ESLint的exhaustive-deps规则能明确识别:你依赖的是prop对象下的具体属性值,而非prop对象本身的引用。只要prop.value的实际值不变,就算prop对象整体的引用发生变化(比如父组件重新渲染时传入新的props对象),这个effect也不会被触发,规则认为这种写法精准且安全,因此不会抛出警告。
2. prop.func触发警告的原因
prop.func是函数类型,且你的示例中父组件App传递的是内联匿名函数——每次App渲染时,这个函数都会被重新创建,生成新的引用。
ESLint的exhaustive-deps规则对函数类型的依赖检查更严格:它会认为你在effect中调用的prop.func()本质上依赖prop对象的上下文,仅依赖prop.func可能遗漏prop对象其他变化带来的潜在问题;更关键的是,内联函数的频繁重建会导致effect每次都执行,违背了依赖列表优化渲染的初衷,因此规则抛出警告提示你确认依赖逻辑。
是否需要把prop添加到两个useEffect的依赖列表?
第一个useEffect(依赖prop.value):不需要
我们的核心需求是仅在prop.value的值变化时执行effect,若改成依赖prop对象,只要prop的引用变化(哪怕value没改),effect都会重复执行,这会造成不必要的性能损耗,不符合预期。第二个useEffect(依赖prop.func):不推荐直接添加prop,更优方案是稳定函数引用
直接把prop加入依赖列表,同样会导致prop引用变化时effect就执行,无法解决内联函数频繁重建的问题。正确的做法是在父组件中用useCallback包裹函数,让它的引用保持稳定:
// App组件中优化函数引用 import { useCallback } from 'react'; function App() { const stableFunc = useCallback(() => { console.log("function"); }, []); // 空依赖数组,函数仅在组件首次渲染时创建一次 return ( <Box func={stableFunc} value={"value"} ></Box> ); }
此时在Box组件中,useEffect的依赖列表[prop.func]就不会再触发警告,同时effect只会在stableFunc的引用真正变化时执行(这里因为是空依赖,所以只会执行一次)。
如果确实无法修改父组件的函数传递方式,也可以通过ESLint注释临时忽略警告,但这是下策,建议优先通过useCallback稳定函数引用。
内容的提问来源于stack exchange,提问作者Robin L

