Обновление состояния создает бесконечный цикл

Почему присвоение setTimeSlotsList(fetchAPI(day)) создает бесконечный цикл?

Кажется, что поток кода работает, когда я просто console.info(fetchAPI(day)) тестирую.

const [timeSlotsList, setTimeSlotsList] = useState([])

function FormValues () {
  const { values } = useFormikContext();
  const day = new Date(values.date)

  useEffect(() => {
    setTimeSlotsList(fetchAPI(day))
  }, [values.date]);
}

const AvailableTimes = (props) => {
  const timeSlots = props.data.map(time =>
    <option value = {time}>{time}</option>
  )
  return (
    <>{timeSlots}</>
  )
}

function updateTime (valueTime) {
  return (
    setTimeSlotsList(
      timeSlotsList.filter(a => a !== valueTime)
    )
  )
}

Функция fetchAPI показана ниже:

const seededRandom = function (seed) {
  var m = 2**35 - 31;
  var a = 185852;
  var s = seed % m;
  return function () {
    return (s = s * a % m) / m;
  };
}

const fetchAPI = function(date) {
  let result = [];
  let random = seededRandom(date.getDate());

  for (let i = 17; i <= 23; i++) {
    if (random() < 0.5) {
      result.push(i + ':00');
    }
    if (random() < 0.5) {
      result.push(i + ':30');
    }
  }
  return result;
};

Что такое значения.дата? Это примитивный тип или ссылочный тип?

Armen 16.08.2024 11:07

Не могли бы вы сложить все части головоломки сразу? Я не совсем понимаю, почему вы добавляете их по частям. Где код setTimeSlotsList, а также контекст?

Armen 16.08.2024 11:13

это ссылочный тип данных. «values.date» — это значение, полученное из входных данных с типом = «дата».

Anthony 16.08.2024 11:15

@Armen Я отредактировал код выше, чтобы показать полную картину.

Anthony 16.08.2024 11:21

Спасибо. Вы используете useState вне компонента или это опечатка?

Armen 16.08.2024 11:28

@Armen const [timeSlotsList, setTimeSlotsList] = useState ([]) объявляется внутри основного компонента. вне внутренних функций, таких как fetchAPI....

Anthony 16.08.2024 11:32

Кажется, вы предоставили не весь код. Пожалуйста, предоставьте полную часть, чтобы я мог скопировать и запустить ее. Без полного кода я не смогу дать правильный ответ.

Armen 16.08.2024 11:37

@Армен, я пробовал, но это не позволяет мне вставить сюда весь код. там написано, что это слишком долго.

Anthony 16.08.2024 11:40

Возможно, вы могли бы использовать кодовый блок или другой инструмент, чтобы более эффективно делиться им.

Armen 16.08.2024 11:43

Редко нам нужен этот код для ответа на вопрос. Хороший способ найти проблему — создать копию (вилку или ветку) вашего проекта. Затем удалите все навороты, которые не имеют отношения к вопросу. Посмотрите, сможете ли вы найти минимальный объем кода, необходимый для создания проблемы. Во многих случаях вы решите свою собственную проблему, сделав это. Если вы все еще не знаете, в чем проблема после сокращения кода, минимальный объем кода должен поместиться в вопрос о переполнении стека. См.: stackoverflow.com/help/minimal-reproducible-example

3limin4t0r 16.08.2024 11:59

Пожалуйста, отредактируйте , включив в него полный и понятный минимальный воспроизводимый пример, чтобы читатели могли видеть и понимать, что вы делаете и когда это делают. Если есть ошибки, пожалуйста, включите полное сообщение об ошибке и все сопутствующие трассировки стека, а также любые конкретные шаги воспроизведения для создания проблемы, если они необходимы для понимания проблемы.

Drew Reese 16.08.2024 19:06

Мне удалось решить эту проблему, создав еще один вызов useEffect вне функции FormValues, который вызывает повторную визуализацию, приводящую к бесконечному циклу.

Anthony 17.08.2024 10:13
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
4
12
79
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Хук useEffect в React предназначен для запуска функции обратного вызова при изменении одной из зависимостей в массиве зависимостей. Здесь values.date — это зависимость. Поэтому каждый раз, когда это меняется, запускается useEffect. Эффект запускается при изменении значения value.date, что срабатывает setTimeSlotsList(fetchAPI(day)). Если fetchAPI(day) каким-то образом вызывает изменение в Values.date, запускается новый рендеринг, и useEffect запускается снова, потому что Values.date — это новый объект/ссылка. Это создает цикл, посколькуvalues.date изменяется при каждом рендеринге.

насколько я вижу, функция fetchAPI, похоже, не вызывает никаких изменений в зависимости перехватчика useEffect. Я обновил приведенные выше вопросы, чтобы показать функцию fetchAPI.

Anthony 16.08.2024 11:06
Ответ принят как подходящий

Мне удалось решить эту проблему, создав еще один вызов useEffect вне функции FormValues, который вызывает повторную визуализацию, приводящую к бесконечному циклу.

  useEffect(() => {
    const day = new Date(dateSelected)
        setTimeSlotsList(fetchAPI(day))
  }, [dateSelected]);
  
  const FormValues = () => {
    const { values } = useFormikContext();

      useEffect(() => {
        setDateSelected(values.date)
      }, [values.date]);
  }

Я использую Formik для создания этой формы, что немного усложняет ее.

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