Странное поведение повторного рендеринга с материалом react-диалог пользовательского интерфейса

#javascript #reactjs #material-ui #react-hooks #rendering

#javascript #reactjs #материал-пользовательский интерфейс #реагирующие крючки #рендеринг

Вопрос:

Фон

Итак, я создаю интерфейсный проект для службы доставки на основе React и Material UI. Меня попросили использовать диалоговое окно, которое будет открываться при нажатии на элемент, и там у пользователя будет возможность настроить элемент. Диалоговое окно можно увидеть здесь (очень простое: фотография элемента, название, описание и параметры настройки):

https://ibb.co/GFkpy8Q

(Извините за пикселизацию)

Проблема

Я использую перехватчики react в этом проекте, и поэтому управляю состоянием диалога. Несмотря на простоту, я наткнулся на несколько проблем, связанных с тем, как элементы были перерисованы / не перерисованы (когда ожидалось):

  1. "checked" Реквизит флажков использует Array.some , чтобы увидеть, находится ли уникальный идентификатор флажка в массиве состояний. При нажатии на них флажки не устанавливаются в положение checked. onChange Prop просто помещает значение флажка в массив состояний и устанавливает состояние:
 const [array, setArray] = React.useState([]);
...
<Checkbox
  checked={
    array.some(
      item => item._id === subOption._id
    )
  }
  onChange={() => setArray(array.push(subOption))}
/>
  

onChange Действие работает правильно, так почему "checked" же prop не работает должным образом?

  1. Когда установлен флажок, я хочу добавить рядом с ним поле небольшого количества, чтобы пользователь мог выбрать количество subOption , которое он должен получить. Поэтому я использую следующий хорошо отработанный шаблон:
 {array.some(item => item._id === subOption._id) amp;amp;
  (
    <QuantityField />
  )
}
  

Проблема в том, что поле QuantityField не отображается после того, как флажок установлен.

  1. Если я выхожу из диалогового окна и снова вхожу в него, я внезапно вижу, что установленный флажок установлен, а рядом с ним отображается поле QuantityField 😕

  2. Если я изменю количество элемента с помощью общего поля количества, которое вы можете видеть в левом нижнем углу диалогового изображения, внезапно все установленные флажки будут сняты 😕 Общее поле количества использует собственное состояние и не связано ни с одним из флажков.

Из того, что я смог увидеть после того, как попытался отладить странное поведение, я могу сказать, что действие рендеринга компонента Dialog работает не так, как ожидалось. Состояния обновляются, но не запускают повторный рендеринг дерева диалогов. На самом деле, неправильно говорить, что, поскольку дерево диалога повторно отображается, но «проверенный» реквизит не проверяется повторно во время повторного рендеринга; но полное снятие и повторное монтирование диалога приводит к исправлению дерева.

Надеюсь на интересный ответ. Спасибо.

Ответ №1:

Я бы изменил то, как вы используете setArray . Смотрите из Array.prototype.push() документации:

push() Метод добавляет один или несколько элементов в конец массива и возвращает новую длину массива.

Также использование .push() состояния не допускается, потому что никогда не следует изменять состояние напрямую.

Предлагаемое решение вместо:

 onChange={() => setArray(prevState => [...prevState, subOption])}