Почему useEffect делает бесконечный цикл, если передать второй параметр как массив и внутри поместить пустой объект

У меня есть объект с параметрами фильтра для 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]);

По умолчанию объект пуст, но это делает бесконечный цикл, если я передаю пустой объект в массиве в качестве второго параметра. Я не понимаю, почему? Пожалуйста, может кто-нибудь объяснить мне, почему и как это решить.

Формы c голосовым вводом в React с помощью Speechly
Формы c голосовым вводом в React с помощью Speechly
Пытались ли вы когда-нибудь заполнить веб-форму в области электронной коммерции, которая требует много кликов и выбора? Вас попросят заполнить дату,...
Flatpickr: простой модуль календаря для вашего приложения на React
Flatpickr: простой модуль календаря для вашего приложения на React
Если вы ищете пакет для быстрой интеграции календаря с выбором даты в ваше приложения, то библиотека Flatpickr отлично справится с этой задачей....
Приложение для отслеживания бюджета на React js для начинающих
Приложение для отслеживания бюджета на React js для начинающих
Обучение на практике - это проверенная тема для достижения успеха в любой области. Если вы знаете контекст фразы "Практика делает человека...
Стоит ли использовать React в 2022 году?
Стоит ли использовать React в 2022 году?
В 2022 году мы все слышим о трендах фронтенда (React, Vue), но мы не знаем, почему мы должны использовать эти фреймворки, когда их использовать, а...
Как передать состояние или данные в react-router v6
Как передать состояние или данные в react-router v6
react-router - это лучшая библиотека для работы с маршрутизацией в reactjs. С помощью react-router вы передаете состояние или данные от одного...
0
0
27
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Каждый раз, когда функция запускается, она создает здесь новый пустой объект:

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

Другие вопросы по теме