使用React 16.8.6(在之前的版本16.8.3上很好),当我试图阻止fetch请求上的无限循环时,我得到了这个错误:
./src/components/BusinessesList.js
Line 51: React Hook useEffect has a missing dependency: 'fetchBusinesses'.
Either include it or remove the dependency array react-hooks/exhaustive-deps
我一直无法找到一个解决办法来停止这个无限循环。我想远离使用useReducer()。我确实找到了关于'筋疲力尽-deps' lint规则#14920的讨论[ESLint]反馈,其中一个可能的解决方案是,如果你认为你知道你在做什么,你可以总是// ESLint - disabled -next-line react-hooks/详尽-deps。我对我正在做的事情没有信心,所以我还没有尝试实现它。
我有这个当前的设置,React钩子useEffect连续运行永远/无限循环,唯一的评论是关于useCallback(),我不熟悉。
我目前如何使用useEffect()(我只想在开始时运行一次,类似componentDidMount()):
useEffect(() => {
fetchBusinesses();
}, []);
const fetchBusinesses = () => {
return fetch("theURL", {method: "GET"}
)
.then(res => normalizeResponseErrors(res))
.then(res => {
return res.json();
})
.then(rcvdBusinesses => {
// some stuff
})
.catch(err => {
// some error handling
});
};
./src/components/BusinessesList.js
Line 51: React Hook useEffect has a missing dependency: 'fetchBusinesses'.
Either include it or remove the dependency array react-hooks/exhaustive-deps
这不是一个JavaScript/React错误,而是一个ESLint (ESLint -plugin- React -hooks)警告。
它告诉你这个钩子依赖于fetchBusinesses函数,所以你应该把它作为一个依赖项传递。
useEffect(() => {
fetchBusinesses();
}, [fetchBusinesses]);
如果函数在组件中声明,则可能导致在每次渲染时调用该函数:
const Component = () => {
/*...*/
// New function declaration every render
const fetchBusinesses = () => {
fetch('/api/businesses/')
.then(...)
}
useEffect(() => {
fetchBusinesses();
}, [fetchBusinesses]);
/*...*/
}
因为每次用新的引用重新声明函数时。
正确的做法是:
const Component = () => {
/*...*/
// Keep the function reference
const fetchBusinesses = useCallback(() => {
fetch('/api/businesses/')
.then(...)
}, [/* Additional dependencies */])
useEffect(() => {
fetchBusinesses();
}, [fetchBusinesses]);
/*...*/
}
或者只是在useEffect中定义函数。
更多:[ESLint]关于'枯竭-deps' lint规则#14920的反馈
下一行禁用ESLint即可;
useEffect(() => {
fetchBusinesses();
// eslint-disable-next-line
}, []);
通过这种方式,您使用它就像使用组件挂载(调用一次)一样。
更新
or
const fetchBusinesses = useCallback(() => {
// Your logic in here
}, [someDeps])
useEffect(() => {
fetchBusinesses();
// No need to skip the ESLint warning
}, [fetchBusinesses]);
fetchBusinesses将在每次someDeps更改时被调用。
React也给出了解决方案。他们建议你使用useCallback,它会返回你函数的一个内存版本:
'fetchBusinesses'函数使useEffect钩子(在NN行)的依赖关系在每次渲染时发生变化。为了解决这个问题,将'fetchBusinesses'定义包装到它自己的useCallback() Hook react-hooks/竭-deps中
useCallback使用起来很简单,因为它与useEffect具有相同的签名。区别在于useCallback返回一个函数。
它看起来是这样的:
const fetchBusinesses = useCallback( () => {
return fetch("theURL", {method: "GET"}
)
.then(() => { /* Some stuff */ })
.catch(() => { /* Some error handling */ })
}, [/* deps */])
// We have a first effect that uses fetchBusinesses
useEffect(() => {
// Do things and then fetchBusinesses
fetchBusinesses();
}, [fetchBusinesses]);
// We can have many effects that use fetchBusinesses
useEffect(() => {
// Do other things and then fetchBusinesses
fetchBusinesses();
}, [fetchBusinesses]);
你正在使用useEffect,当你这样做的时候,你经常会想要使用一些变量作为你的组件中的道具或状态。
eslint中有一个规则,它希望你引用useEffect依赖数组中任何不同的道具或状态块。这是控制何时执行useEffect的数组。该规则希望看到它列在数组中,数组决定何时重新运行useEffect函数。
因此,您需要添加[fetchBusinesses],这样警告就会消失。
为什么这个规则要我们把它写在这里?
在某些情况下,使用useEffect而没有正确列出数组内的所有状态和道具,可能会导致奇怪且难以调试的问题。
因此,这条规则有助于避免使用useEffect可能出现的那些难以理解的问题。
现在,任意添加到该数组也会导致错误。所以无论哪种方式,你都遇到了必须解决的bug。根据你的评论,似乎为你解决了这个问题,但我想进一步调查,看看你是否有机会在你的网络选项卡在Chrome中添加fetchBusinesses函数到你的useEffect数组后得到第二个GET请求。