Я создаю компонент React, который принимает источник данных JSON и создает сортируемую таблицу.
Каждой из строк динамических данных присвоен уникальный ключ, но я все еще получаю сообщение об ошибке:
Каждый дочерний элемент в массиве должен иметь уникальную «ключевую» опору.
Проверьте метод визуализации TableComponent.
Мой TableComponent
метод рендеринга возвращает:
<table>
<thead key="thead">
<TableHeader columns={columnNames}/>
</thead>
<tbody key="tbody">
{ rows }
</tbody>
</table>
TableHeader
Компонент представляет собой один ряд , а также имеет уникальный ключ , возложенные на него.
Каждый row
в rows
построен из компонента с уникальным ключом:
<TableRowItem key={item.id} data={item} columns={columnNames}/>
И TableRowItem
выглядит так:
var TableRowItem = React.createClass({
render: function() {
var td = function() {
return this.props.columns.map(function(c) {
return <td key={this.props.data[c]}>{this.props.data[c]}</td>;
}, this);
}.bind(this);
return (
<tr>{ td(this.props.item) }</tr>
)
}
});
В чем причина ошибки уникального ключа?
javascript
reactjs
Бретт ДеВуди
источник
источник
key
свойство. Это поможет ReactJS найти ссылки на соответствующие узлы DOM и обновить только содержимое внутри разметки, но не перерисовывать всю таблицу / строку.rows
массивом или более предпочтительно jsfiddle? Вам не нужноkey
свойство наthead
иtbody
, кстати.Ответы:
Вы должны добавить ключ к каждому дочернему элементу, а также к каждому элементу внутри дочерних элементов .
Таким образом, React может справиться с минимальным изменением DOM.
В вашем коде каждый
<TableRowItem key={item.id} data={item} columns={columnNames}/>
пытается представить некоторых детей внутри себя без ключа.Проверьте этот пример .
Попробуйте удалить элемент
key={i}
из<b></b>
элемента div (и проверьте консоль).В образце, если мы не даем ключ к
<b>
элементу , и мы хотим обновить толькоobject.city
, React потребности повторной визуализации всю строку против всего элемента.Вот код:
Ответ, размещенный @Chris внизу, более детален, чем этот ответ. Пожалуйста, посмотрите на https://stackoverflow.com/a/43892905/2325522
Реагировать на документацию о важности ключей в сверке: ключи
источник
key
значение для подпорки уникально для каждого элемента, и вы добавляетеkey
подпорку к компоненту, ближайшему к границам массива. Например, в React Native сначала я пытался поместитьkey
опору в<Text>
компонент. Однако мне пришлось поместить его в<View>
компонент, который является родителем<Text>
. если Array == [(View> Text), (View> Text)], вам нужно поместить его в View. Не текст.Будьте осторожны при переборе массивов !!
Распространено заблуждение, что использование индекса элемента в массиве является приемлемым способом подавления ошибки, с которой вы, вероятно, знакомы:
Однако во многих случаях это не так! Это анти-паттерн, который в некоторых ситуациях может привести к нежелательному поведению .
Понимание
key
опорыReact использует
key
реквизит для понимания отношения компонента к элементу DOM, которое затем используется для процесса согласования . Поэтому очень важно, чтобы ключ всегда оставался уникальным , иначе есть хороший шанс, что React смешает элементы и изменит неправильный. Также важно, чтобы эти ключи оставались статичными течение всех повторных рендеров, чтобы поддерживать наилучшую производительность.Это сказанное, не всегда нужно применять вышеупомянутое, если известно, что массив полностью статичен. Тем не менее, по возможности рекомендуется применять лучшие практики.
Разработчик React сказал в этом выпуске GitHub :
Короче говоря,
key
должно быть:С использованием
key
опоруСогласно приведенному выше объяснению, внимательно изучите следующие примеры и постарайтесь по возможности реализовать рекомендуемый подход.
Плохо (Потенциально)
Возможно, это самая распространенная ошибка, возникающая при переборе массива в React. Этот подход технически не «неправильный» , он просто… «опасный», если вы не знаете, что делаете. Если вы перебираете статический массив, то это совершенно правильный подход (например, массив ссылок в вашем меню навигации). Однако, если вы добавляете, удаляете, переупорядочиваете или фильтруете элементы, вам следует быть осторожным. Взгляните на это подробное объяснение в официальной документации.
Показать фрагмент кода
В этом фрагменте мы используем нестатический массив и не ограничиваемся его использованием в качестве стека. Это небезопасный подход (вы поймете почему). Обратите внимание, как при добавлении элементов в начало массива (в основном без смещения) значение каждого из них
<input>
остается на месте. Почему? Потому чтоkey
не уникально идентифицирует каждый элемент.Другими словами, сначала
Item 1
имеетkey={0}
. Когда мы добавим второй элемент, верхний элемент становитсяItem 2
, а затем вItem 1
качестве второго пункта. Однако сейчасItem 1
естьkey={1}
и неkey={0}
больше. Вместо этогоItem 2
теперь естьkey={0}
!!Таким образом, React считает, что
<input>
элементы не изменились, потому чтоItem
ключ with0
всегда находится вверху!Так почему такой подход только иногда плох?
Такой подход опасен только в том случае, если массив каким-то образом фильтруется, переставляется или элементы добавляются / удаляются. Если он всегда статичен, то использовать его совершенно безопасно. Например, с
["Home", "Products", "Contact us"]
помощью этого метода можно безопасно перемещаться по меню навигации, например, так как вы, вероятно, никогда не добавите новые ссылки и не переставите их.Короче говоря, вот когда вы можете безопасно использовать индекс как
key
:Если бы мы вместо того, чтобы , в сниппет выше, толкнул добавленный элемент в конец массива, порядок для каждого существующего объекта всегда будет правильным.
Очень плохо
Хотя этот подход, вероятно, гарантирует уникальность ключей, он всегда заставляет реагировать на повторную визуализацию каждого элемента в списке, даже если это не требуется. Это очень плохое решение, так как оно сильно влияет на производительность. Не говоря уже о том, что нельзя исключать возможность столкновения клавиш в том случае,
Math.random()
если дважды получается одно и то же число.Отлично
Это, пожалуй, лучший подход, поскольку он использует свойство, уникальное для каждого элемента в наборе данных. Например, если
rows
содержит данные, извлеченные из базы данных, можно использовать первичный ключ таблицы ( который обычно представляет собой число с автоинкрементом ).Хорошо
Это тоже хороший подход. Если ваш набор данных не содержит данных, которые гарантируют уникальность ( например, массив произвольных чисел ), существует вероятность столкновения ключа. В таких случаях лучше всего вручную генерировать уникальный идентификатор для каждого элемента в наборе данных, прежде чем выполнять его итерацию. Предпочтительно при монтировании компонента или при получении набора данных ( например, от
props
или из асинхронного вызова API ), чтобы сделать это только один раз , а не каждый раз, когда компонент повторно выполняет рендеринг. Уже есть несколько библиотек, которые могут предоставить вам такие ключи. Вот один пример: реакция-ключ-индекс .источник
toString()
для преобразования в строку, а не в качестве числа. Это важно помнить?key
. Не уверен, почему они конвертируют это.key
любом случае всегда получается String.Это может или не может помочь кому-то, но это может быть краткий справочник. Это также похоже на все ответы, представленные выше.
У меня есть много мест, которые генерируют список, используя структуру ниже:
После небольшой проб и ошибок (и некоторых разочарований) добавление ключевого свойства к внешнему блоку разрешило его. Также обратите внимание, что тег <> теперь заменен тегом.
Конечно, я наивно использовал итерационный индекс (index) для заполнения значения ключа в приведенном выше примере. В идеале вы должны использовать что-то уникальное для элемента списка.
источник
Предупреждение: каждый дочерний элемент в массиве или итераторе должен иметь уникальную «ключевую» опору.
Это предупреждение, поскольку для элементов массива, которые мы собираемся перебрать, потребуется уникальное сходство.
React обрабатывает рендеринг компонентов в виде массивов.
Лучший способ решить эту проблему - предоставить индекс для элементов массива, которые вы собираетесь перебирать. Например:
индекс React встроенный реквизит.
источник
Просто добавьте уникальный ключ к своим компонентам
источник
Проверьте: ключ = undef !!!
Вы также получили предупреждение:
если ваш код завершен правильно, но если на
someValue не определено !!! Пожалуйста, проверьте это сначала. Вы можете сэкономить часы.
источник
Лучшее решение для определения уникального ключа в реакции: внутри карты вы инициализировали имя поста, затем ключ определяете по ключу = {post.id} или в моем коде вы видите, что я определяю имя элемента, а затем я определяю ключ по ключу = {item.id }:
источник
Это предупреждение, но решение этой проблемы сделает рендеринг намного быстрее ,
Это потому, что
React
необходимо однозначно идентифицировать каждый элемент в списке. Скажем, если состояние элемента этого списка изменяется в ReactsVirtual DOM
то React должен выяснить, какой элемент был изменен и где в DOM его нужно изменить, чтобы DOM браузера синхронизировался с Reacts Virtual DOM.В качестве решения просто введите
key
атрибут для каждогоli
тега. Этоkey
должно быть уникальным значением для каждого элемента.источник
key
опору. Если вы его не предоставите, React назначит его автоматически (текущий индекс итерации).key={i}
. Так что это зависит от данных, которые содержит ваш массив. Например, если у вас есть список["Volvo", "Tesla"]
, то, очевидно, Volvo идентифицируется по ключу,0
а Tesla1
- потому, что в этом порядке они будут отображаться в цикле. Теперь, если вы измените порядок массива, ключи поменяются местами. Для React, поскольку «объект»0
все еще находится наверху, он скорее будет интерпретировать это изменение как «переименование», а не как переупорядочение. Правильные ключи здесь должны были бы быть в порядке, а1
затем0
. Вы не всегда меняете порядок во время выполнения, но когда это происходит, это риск.Это решит проблему.
источник
Я столкнулся с этим сообщением об ошибке, потому что
<></>
его возвращали для некоторых элементов в массиве, когда вместо этогоnull
нужно было возвращать.источник
Я исправил это с помощью Guid для каждого ключа следующим образом: Генерация Guid:
И затем присвоение этого значения маркерам:
источник
По сути, вы не должны использовать индекс массива в качестве уникального ключа. Скорее вы можете использовать a
setTimeout(() => Date.now(),0)
для установки уникального ключа или уникального uuid или любым другим способом, который будет генерировать уникальный идентификатор, но не индекс массива в качестве уникального идентификатора.источник