Есть ли способ получить React для автоматического определения "ключей" для детей?

Я изучаю React, и я наткнулся на эту причуду с "динамическими детьми".

Преамбула с примером кода:

// Render Pass 1
<Card>
  <p>Paragraph 1</p>
  <p>Paragraph 2</p>
</Card>

// Render Pass 2
<Card>
  <p>Paragraph 2</p>
</Card>

Во втором проходе render() кажется, что работа vdom отличается тем, что он удаляет второго ребенка, а затем преобразует текст в первом, чтобы сказать "Параграф 2.", Это быстро, но вы увидите странные вещи, если вам нужно состояние, чтобы продолжать говорить... второй ребенок!

So React предлагает использовать "key" для этих тегов. Теперь vdom diffing будет неожиданным, и вы увидите, что состояние сохраняется в renders().

Мой вопрос: есть ли способ заставить React установить "ключи" самостоятельно, а не делать это так, как они предлагают?

Ответ 1

Нет, нет.

Поведение React по умолчанию, когда нет указанных ключей, - это использовать, как вы заметили, наивный подход, обновляющий компоненты на месте. Функционально это эквивалентно заданию ключа по умолчанию в соответствии с индексом элемента относительно его братьев и сестер. В вашем примере это будет выглядеть так:

// Render Pass 1
<Card>
  <p key={0}>Paragraph 1</p>
  <p key={1}>Paragraph 2</p>
</Card>

// Render Pass 2
<Card>
  <p key={0}>Paragraph 2</p>
</Card>

Вот почему вы видите текст для первого элемента, преобразованного, но, как вы заметили, это не всегда оптимальный результат. Итак, почему React не может использовать более интеллектуальный автоматический ключ? Ответ заключается в том, что для этого есть только два варианта, и ни один из них не идеален:

  • Они могут сделать определенные предположения о структуре вашего приложения. В вашем кратком примере для человека очевидно, что абзацы должны быть сопоставлены в соответствии с их текстовым контентом. Но это не обязательно верно во всех случаях, и трудно распространить эту логику на более сложные сценарии с настраиваемыми элементами, множеством реквизитов, вложенными дочерними элементами и т.д.

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

    Существует множество алгоритмов, которые пытаются найти минимальные наборы операций для преобразования списка элементов. Расстояние Левенштейна может найти минимум с помощью вставки, удаления и замены одного элемента в O (n 2). Даже если мы будем использовать Levenshtein, это не находит, когда node переместился в другую позицию, и алгоритмы для этого имеют гораздо худшую сложность.

Таким образом, в любом случае любое преимущество "автоматического назначения ключей" также имеет ряд недостатков. В конце концов, это не стоит того, особенно учитывая, что в большинстве случаев назначение ключей вручную на самом деле не так сложно или громоздко. С другой стороны, на той же странице документации:

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