gpt4 book ai didi

javascript - 奇怪的useEffect无限循环

转载 作者:行者123 更新时间:2023-12-04 16:37:44 25 4
gpt4 key购买 nike

在我们用于处理 apiCalls 的钩子(Hook)中看到一些奇怪的事情,其中​​ api 响应结构的突然变化触发了我们应用程序中的无限请求循环。我已将其简化为重现错误的最低要求。

import React, {useEffect, useState, useMemo} from 'react';

const mockedApiCall = (resolvedValue, time) =>
new Promise((resolve, reject) => setTimeout(() => resolve(resolvedValue), time));

const useHook = (query) => {
const [error, setError] = useState(null);
const [data, setData] = useState([]);

useEffect(() => {
const asyncOperation = async () => {
const response = await mockedApiCall([], 1000);

// Testing something i know will fail:
const mappedData = response.data.map(a => a);

// if the above didn't fail we would update data
setData(mappedData);
};

// Clear old errors
setError(null);
// trigger operation
asyncOperation().catch(e => {
console.log('fail');
setError('Some error');
});
}, [query]);

return [data, error];
}


const HookIssue = props => {
const [data, error] = useHook({foo: 'bar'}); // Creates infinite loop
//const [data, error] = useHook('foo') // only fails a single time

// Alternative solution that also doesn't create infinite loop
// const query = useMemo(() => ({foo: 'bar'}), []);
// const [data, error] = useHook(query);


return null;
};

export default HookIssue;

有人知道这里发生了什么吗?该钩子(Hook)应该只监听查询变量的变化,但在某些情况下会陷入无限循环。

编辑:为了给这个问题增加一些奇怪的地方,如果我删除 useEffect 中的两个 setError 调用中的一个(或两个),它也会阻止无限循环。

最佳答案

你得到这个循环是因为你将一个对象传递给 useHook()。对象是引用类型——也就是说,它们不是由它们的值定义的。由于这个原因,以下语句评估为 false:

{ foo: "bar" } === { foo: "bar" }

每次HookIssue被渲染时,都会创建一个{ foo: "bar"} 的新对象。这被传递给依赖数组中的 useEffect(),但是因为对象是引用类型——并且每个渲染器上的每个对象都有不同的引用——React 将始终“看到”query 值已更改。

这意味着每次asyncOperation结束,都会引起HookIssue的重新渲染,从而导致触发另一个效果.

要解决这个问题,您需要将值类型传递给依赖项数组,或者您需要通过使用“稳定”query 对象useMemo() 的。

关于javascript - 奇怪的useEffect无限循环,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67300055/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com