使用useEffect挂钩时出现问题,它生成了无限循环。
我有一个列表,该页面在汇编页面后立即加载,并且在“开发人员”状态下发现新记录时也应更新。
查看代码:
const [developers, setDevelopers] = useState<DevelopersData[]>([]);
const getDevelopers = async () => {
await api.get('/developers').then(response => {
setDevelopers(response.data);
});
};
// This way, the loop does not happen
useEffect(() => {
getDevelopers();
}, []);
// This way, infinte loop
useEffect(() => {
getDevelopers();
}, [developers]);
console.log(developers)
如果我删除了对useEffect的第二个参数的开发人员依赖性,则不会发生循环,但是,当找到新记录时,列表不会更新。如果我在useEffect的第二个参数中插入“ developers”,则列表会自动更新,但是会陷入无限循环。
我在做什么错了?
完整代码(带有组件):https://gist.github.com/fredarend/c571d2b2fd88c734997a757bac6ab766
答案 0 :(得分:2)
useEffect
的依赖项使用引用相等,而不是深度相等。 (如果出于某种原因需要进行深度相等比较,请查看use-deep-compare-effect
。)
API调用始终返回一个新的数组对象,因此其引用/标识与之前的引用/标识不同,从而触发useEffect
以再次触发效果,等等。
鉴于没有其他任何东西可以调用setDevelopers
,即除非有效果触发的API调用,否则developers
无法更改,实际上并不需要{{1} }作为对developers
的依赖;您可以将一个空数组作为deps:useEffect
。该效果只会被调用一次。
编辑:在澄清说明后,
我以左侧表格的形式注册开发人员。[...]我希望列表在注册新开发人员后立即得到更新。
这是做事的一种方式:
这里的想法是useEffect(() => ..., [])
只会在组件安装时自动加载。当用户通过developers
添加新的开发人员时,我们会在将新的开发人员发布到后端时,适时地更新本地AddDeveloperForm
的状态。无论发布是否失败,我们都会从后端重新加载列表,以确保我们拥有最新的 real 状态。
developers
答案 1 :(得分:0)
问题在于您的getDevelopers
函数调用了setDevelopers
函数,该函数更新了developers
变量。当您的developers
变量更新后,它将触发useEffect
函数
useEffect(() => {
getDevelopers();
}, [developers]);
因为developers
是传递给它的依赖项之一,所以过程重新开始。
每次更新数组中的变量(作为useEffect的第二个参数传递)时,都会触发useEffect
函数
答案 2 :(得分:0)
在useEffect的第二个参数中使用空数组[]
。
这导致内部代码仅在安装父组件时运行。
useEffect(() => {
getDevelopers();
}, []);