如果将第二个参数作为数组传递并放入空对象,为什么 useEffect 会导致无限循环

Why useEffect makes infinitive loop if pass the second param as array and inside put empty object

我有 API 过滤器参数的对象,我传递给 useEffect 的这个对象。

    let dataForFilter = typeof defaultFormData[someKey] !== 'undefined'
    ? defaultFormData[someKey]
    : {};

    for (let key in props.route.params) {
        if (props.route.params.hasOwnProperty(key)) {
            dataForFilter[key] = props.route.params[key];
        }
    }

    useEffect(() => {
        async function fetchData() {
            const body = {
               ...dataForFilter,
            };
            loadData(url, body);
        }
        fetchData();
    }, [dataForFilter]);

默认情况下对象是空的,但是如果我将数组中的空对象作为第二个参数传递,这会造成无限循环。 我不明白为什么?请有人能解释一下为什么以及如何解决这个问题。

每次函数运行时,都会在此处创建一个新的空对象:

let dataForFilter = typeof defaultFormData[someKey] !== 'undefined'
    ? defaultFormData[someKey]
    : {};

因此,如果 defaultFormData[someKey] 不存在,则依赖项数组的值会在每次渲染时更改。空对象不等于自身。

console.log([{}] === [{}]);
console.log({} === {});

改为在函数外部创建对象,使其引用稳定。

const emptyObj = {};
const MyComponent = ({ defaultFormData }) => {
  // ...
  let dataForFilter = typeof defaultFormData[someKey] !== 'undefined'
    ? defaultFormData[someKey]
    : emptyObj;

在您的 useEffect 中,调用一个函数来重新渲染组件。在您的 useEffect 依赖项(末尾的数组)中,您传入了 dataForFilter 作为依赖项。这意味着,只要 dataForFilter 发生变化,就会再次调用 useEffect。但是由于 useEffect 使组件重新渲染,并且 dataForFilter 没有被定义为状态而是组件内部的普通变量,因此它将被重新定义为另一个值(注意:即使具有相同值的对象也不是与之前相同的对象)。如果您希望在组件呈现时调用任何 useEffect 一次,请传递一个空数组作为依赖项,如下所示:

let dataForFilter = typeof defaultFormData[someKey] !== 'undefined' // <-- dataForFilter gets evaluated again and changes its value, which calls the useEffect
    ? defaultFormData[someKey]
    : {};

    for (let key in props.route.params) {
        if (props.route.params.hasOwnProperty(key)) {
            dataForFilter[key] = props.route.params[key];
        }
    }

    useEffect(() => {
        async function fetchData() {
            const body = {
               ...dataForFilter,
            };
            loadData(url, body); // <-- You rerender the component somewhere in this function, dataForFilter gets defined again and is another object (with the same value BUT still another object)
        }
        fetchData();
    }, []); // <-- Empty array as dependency, only gets called once