Что заставляет текст поля ввода не переупорядочиваться в примере ReactJS страницы Reconciliation?

На странице ReactJS Reconciliation есть два примера:

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

По состоянию на 18 февраля 2020 г. нет информации о том, как воспроизвести проблему на странице. Я пытался несколько раз нажать "Добавить в начало" или "в конец" и изменить порядок списка, и, похоже, они работали нормально. Только позже я узнал, что вам нужно ввести какой-то текст в поле, а затем просто "Добавить новое в конец", сделать это три раза и изменить порядок списка.

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

Две программы отличаются использованием

<ToDo key={index} {...todo} />

против

<ToDo key={todo.id} {...todo} />

Также есть небольшая перестановка кода и использование todoCounter против toDoCounter (капитал D) между двумя версиями, и мне интересно, почему, и команда React может исправить это позже. Но вы можете изменить первую версию изkey={index} к key={todo.id} и вы также можете увидеть, что проблема решена.

Но затем, когда я заглянул в код, поле ввода фактически не добавляет текстовые данные в свойство состояния. list(массив). Толькоid а также createdAt добавляются за новую запись в list.

Итак, пока мы можем сказать, используя key={todo.id} исправили проблему, что изначально было причиной проблемы?

Можно сказать, что id а также createdAtотсортированы правильно. Что не отсортировано правильно, так это поля ввода... но в соответствии с правилом согласования, чтобы решить, обновлять ли фактические элементы DOM на странице, новое поддерево виртуального DOM сравнивается с предыдущим поддеревом виртуального DOM.

Теперь "свойство" поля ввода value не является частью виртуальной DOM, если только React не помещает value в виртуальный DOM.

Поэтому при рекурсивном "различении" React должен думать, что все поля ввода одинаковы. Вот как это работало: если бы мы использовалиkey={index}, теперь React сравнил каждый столбец в текущем виртуальном поддереве DOM с предыдущим и увидел, что ячейки "ID" и "createAt" различаются, что привело к обновлению фактического DOM. React все равно видел поля ввода и не удосужился принудительно обновить фактическую DOM.

Однако, если мы используем key={todo.id}, теперь React подумает, что вся строка другая, потому что строка "id" изменилась. Таким образом, React принудительно обновит фактическую DOM для всей строки, включая поле ввода.

Таким образом, мы можем сказать, что эта ошибка возникает только тогда, когда некоторые данные не находятся в виртуальном поддереве DOM... что бывает редко, как в данном случае. В других случаях все данные будут выданыrender() компонента класса или return функционального компонента и, следовательно, может сказать ReactJS, что "да, принудительно обновить фактическую DOM".

Неужели так это работало?

1 ответ

Использование индекса в качестве ключей очень опасно и настоятельно не рекомендуется.

Например, если вы удаляете элемент из середины списка, его место займет другой элемент, React нужен уникальный ключ для распознавания элемента DOM как отдельного / независимого элемента, а не чего-то временного или бесполезного.

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

Но в вашем случае React не знает, какое задание принадлежит какому идентификатору, индексы не являются идентификатором списка дел, это числа, которые были сгенерированы по порядку.

Представьте себе это

Todos:
id 1
todo: "take out the trash"

id 2
todo: "make dinner"

if you sort your todos by the shortest string
it will end up like this:
2
1

нормальный порядок:

1
2

Независимо от того, как вы сортируете свой список и меняете его порядок, если вы скажете React использовать индексы, он всегда будет отображать его следующим образом:

1
2
3
4
...etc

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

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