使用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
});
};
如果您没有在除效果之外的任何地方使用fetchBusinesses方法,您可以简单地将其移动到效果中并避免警告
useEffect(() => {
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
});
};
fetchBusinesses();
}, []);
然而,如果您在效果之外使用fetchBusinesses,则必须注意两件事
是否有任何问题,你不传递fetchBusinesses作为方法时,它被使用在装载与它的封闭?
你的方法是否依赖于它从封闭包中接收到的一些变量?你不是这样的。
在每次渲染时,fetchBusinesses将被重新创建,因此将它传递给useEffect将会导致问题。因此,如果要将fetchBusinesses传递给依赖数组,首先必须记住它。
总而言之,我想说的是,如果你在useEffect之外使用fetchBusinesses,你可以使用// eslint-disable-next-line react-hooks/ -deps禁用该规则,否则你可以将方法移动到useEffect内部
要禁用规则,可以这样编写
useEffect(() => {
// other code
...
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [])
你可以通过传递一个引用来消除这个Es-lint警告:
下面提到的例子,但是你可以在这个链接上观看解决方案:https://www.youtube.com/watch?v=r4A46oBIwZk&t=8s
警告:
第13:8行:反应。useEffect缺少依赖项:'history'和'currentUser?.role'。要么包含它们,要么删除依赖数组react-hooks/ exhaustion -deps
React.useEffect(() => {
if (currentUser?.role !== "Student") {
return history.push("/")
}
}, [])
解决方法:
步骤1:将业务逻辑移到单独的const中。
现在的警告是:React Hook React。useEffect有一个缺失的依赖:' rolecheck '。
const roleChecking = () =>{
if (currentUser?.role !== "Student") {
return history.push("/")
}
}
React.useEffect(() => {
roleChecking()
}, [])
最后一步是创建对函数的引用:
const roleRef = React.useRef();
const roleChecking = () => {
if (currentUser?.role !== "Student") {
return history.push("/");
}
};
roleRef.current = roleChecking;
React.useEffect(() => {
return roleRef.current();
}, [currentUser?.role]);
实际上,在使用钩子进行开发时,警告非常有用。但在某些情况下,它会刺痛你。特别是当您不需要监听依赖项更改时。
如果你不想将fetchBusinesses放在钩子的依赖项中,你可以简单地将它作为参数传递给钩子的回调函数,并将fetchBusinesses设置为它的默认值,如下所示:
useEffect((fetchBusinesses = fetchBusinesses) => {
fetchBusinesses();
}, []);
这不是最佳实践,但在某些情况下可能有用。
同样,正如Shubham所写的,你可以添加下面的代码来告诉ESLint忽略钩子的检查。
// eslint-disable-next-line react-hooks/exhaustive-deps
下一行禁用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]);