Реагировать на условие гонки хуков useState с массивом

Таким образом, мой компонент настроен как контейнер, который может иметь x дочерних элементов, пользователь не может продвигаться вперед, пока каждый из дочерних компонентов не будет «готов» на основе различных условий. Я столкнулся с проблемой, когда некоторые из них настроены на готовность при первоначальном рендеринге без каких-либо условий. Если 2 из них находятся в одном контейнере, каждый из них захватывает один и тот же массив, скажем [false, false], а затем один устанавливает [true, false], а другой [false, true], а затем устанавливается [false, true] в состоянии. Я предполагаю, что это результат асинхронной установки состояния, поэтому он получает старое значение состояния в обоих вызовах. Как я могу это исправить?

  const [readyArray, setReadyArray] = useState(
    new Array(children.length).fill(false)
  );

  const setReady = (val, idx) => {
    let newArray = Array.from(readyArray);
    newArray[idx] = val;
    if (isArrayTrue(newArray)) {
        props.setReady(true);
     }
    setReadyArray(newArray);
  };

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

Я предполагаю, что проблемы связаны с react component life cycle problem, а не с state racing condition, даже если вы правы, состояние реакции - это асинхронная настройка. \n проблема заключается в том, что состояние компонента будет зависеть от длины дочерних элементов, что создает проблему жизненного цикла. Исправление состоит в том, чтобы не использовать children.length, вместо этого использовать большое число, которое всегда больше, чем длина ваших детей.

tim 10.12.2020 05:20
Поведение ключевого слова "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) для оценки ваших знаний,...
2
1
715
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

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

Используйте setReadyArray обратный вызов вместо использования readyArray в замыкании — таким образом, немедленные обновления состояния не будут перезаписывать друг друга:

const setReady = (val, idx) => {
  setReadyArray(readyArray => readyArray.map(
    (orig, i) => i === idx ? orig : val
  ));
};

я не думаю, что может помочь.

tim 10.12.2020 05:21

Есть еще одна сложность, я также проверяю в этой функции, полностью ли массив верен, и если это так, то вызываю другую функцию, которая передается в реквизитах. Я изменил ваш код на этот setReadyArray((readyArray) => { let newArray = readyArray.map((orig, i) => (i === idx ? orig : val)); if (isArrayTrue(newArray)) { props.setReady(true); } return newArray; });, но он все равно не работает

user3645925 10.12.2020 05:23

@user3645925 user3645925 эта проверка должна происходить в отдельном useEffect.

Emile Bergeron 10.12.2020 05:25

По какой-то причине это не работает в случае, когда есть только один элемент? Однако в случае одновременного вызова двух элементов это работает отлично.

user3645925 10.12.2020 05:34

Исправлено, нужно было !== вместо === они поменяли местами троичный оператор true/false

user3645925 10.12.2020 05:38

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