这很诱人,我们都经历过。我们收到关于React钩子中的依赖阵列的react-hooks/exhaustive-deps linting警告。我们试图将依赖关系添加到数组中,然后我们最终出现了无限的重新渲染或其他不理想的行为。
我们有一个看似简单的解决办法:我们可以通过在依赖性数组的正上方放置一个// eslint-disable-next-line ,来忽略这个错误。下面是一个假想的例子。
useEffect(() => {
setCount(count + 1);
// eslint-disable-next-line
}, []);
而这确实是可行的。但随着时间的推移,我发现不禁用这些警告是值得的,相反,找到一种方法来满足依赖数组的要求。
但为什么呢?
有几个原因是值得努力的。
- 你可能确实想在变量发生变化时启动效果(或你要处理的任何钩子)。一开始可能不是这样的,但可能有一些边缘情况,如果你不把变量包括在依赖关系数组中,你的效果逻辑就会失败。
- 一旦你添加了
// eslint-disable-next-line,你现在已经放弃了对未来的依赖关系进行警告的机会。如果你在效果中添加了一个新的依赖项,你将不会因为忘记将其包含在依赖项数组中而被警告。这可能是个大问题,会破坏你的应用程序。
如何去修复这个问题
对于这个警告,比较合适的修复方法取决于情况。
有状态的依赖关系
在前面提到的例子中,你可以在你的setCount 方法中使用一个回调。
useEffect(() => {
setCount((count) => count + 1);
}, []);
现在,count 不是一个依赖关系,所以我们的问题就解决了。
函数的依赖性
让我们考虑下面的例子,在组件的主体中声明一个函数。
const someFunction = (count) => {
// do something with count
};
useEffect(() => {
someFunction(count);
}, [count]);
我们再次得到一个依赖性警告,因为someFunction 应该在依赖性数组中。如果我们直接把它添加到依赖关系数组中,我们可能会得到警告,因为我们刚刚造成了一个无限循环,因为someFunction 在每次渲染时都有不同的引用。
这里的解决方法可能是使用useCallback 钩子来确保someFunction 在渲染之间不改变引用(除非它本身需要在其依赖数组中拥有依赖关系!)。
javascript
const someFunction = useCallback((count) => {
// do something with count
}, []);
useEffect(() => {
someFunction(count);
}, [count, someFunction]);
当其他一切都失败时
当所有其他方法都失败时,你很可能只是在效果中做一些基本的比较,并在必要时跳出。在下面的例子中,如果postid 是undefined ,我们就提前从效果中return 。
useEffect(() => {
if (post.id === undefined) {
return;
}
doSomethingWithPost(post);
}, [post]);
总结
我希望这篇文章能让你相信,值得尝试满足react钩子的依赖性要求,并给你一些方法来做到这一点。