Получение предупреждения о ключевой опоре в Реактите, даже если задан ключ
Проблема
Я получаю это предупреждение:
Предупреждение: каждый дочерний элемент в массиве или итераторе должен иметь уникальную "ключевую" опору. Проверьте метод рендеринга EventTable. Подробнее см. fb.me/react-warning-keys.
response-runtime-dev.js? 8fefd85d334323f8baa58410bac59b2a7f426ea7: 21998 Внимание: каждый дочерний элемент в массиве или итераторе должен иметь уникальную "ключевую" опору. Проверьте способ рендеринга события. Подробнее см. fb.me/react-warning-keys.
Источник
Это EventsTable
:
EventsTable = React.createClass({
displayName: 'EventsTable',
render() {
console.dir(this.props.list);
return (
<table className="events-table">
<thead>
<tr>
{_.keys(this.props.list[0]).map(function (key) {
if (key !== 'attributes') {
return <th>{key}</th>;
}
})}
</tr>
</thead>
<tbody>
{this.props.list.map(function (row) {
return (
<Event key={row.WhatId} data={row} />
);
})}
</tbody>
</table>
)
}
});
Это Event
:
Event = React.createClass({
displayName: 'Event',
render() {
return (
<tr>
{_.keys(this.props.data).map((x) => {
if (x !== 'attributes')
return <td>{this.props.data[x]}</td>;
})}
</tr>
)
}
});
Вопрос
Очевидно, что у меня есть поддержка key
в компоненте <Event />
. И я согласен с тем, что вы должны включать key
в компонент, а не сам HTML (другими словами, теги HTML в компоненте Event
). В официальных документах React:
Ключ должен всегда предоставляться непосредственно компонентам в массиве, а не содержимому HTML-контейнера каждого компонента в массиве:
Я сильно смущен. Почему я получаю предупреждения?
Ответы
Ответ 1
Вы пытались добавить key
в тег <th>
?
<tr>
{_.keys(this.props.list[0]).map(function (key) {
if (key !== 'attributes') {
return <th key={key}>{key}</th>;
}
})}
</tr>
Ответ 2
TL;DR
Каждый раз, когда вы представляете список (используйте map
), добавьте уникальный атрибут key
к элементам списка (самый верхний или "root", возвращенный из обратного вызова map
):
render() {
return (
<div>
{this.props.data.map( element => {
// Place the key on to the returned "root" element.
// Also, in real life this should be a separate component...
return <div key={element.id}>
<span>Id (Name): </span>
<span>{element.id} </span>
<span>({element.name})</span>
</div>;
})}
</div>
)
}
Объяснение
Понимание клавиш в реакторе
Официальная Списки и ключи показывает, как вы должны работать со списками и связанный сверки doc сообщает whys.
В основном, когда React повторно передает компонент, он запускает алгоритм diff, который определяет, что изменилось между новой и предыдущей версиями списка. Сравнение не всегда тривиально, но если в каждом элементе есть уникальный ключ, можно четко определить, что изменилось. См. пример в документе:
<!-- previous -->
<ul>
<li key="2015">Duke</li>
<li key="2016">Villanova</li>
</ul>
<!-- new -->
<ul>
<li key="2014">Connecticut</li>
<li key="2015">Duke</li>
<li key="2016">Villanova</li>
</ul>
Понятно, что добавлен новый элемент с ключом 2014
, так как у нас есть все остальные ключи, и они не были изменены. Без ключей это было бы неясным.
Выбор правильной клавиши
Теперь легко видеть:
- Почему важно, чтобы ключ был уникальным, но только между братьями и сестрами в списке, потому что сравнение происходит только в пределах данного списка предыдущих и новых элементов.
- Клавиша должна оставаться неизменной для одного и того же элемента между предыдущей и новой версиями, иначе мы сравним разные элементы и не сможем отслеживать изменения. Вот почему рекомендуется использовать идентификатор ресурса или (если он не имеет) некоторые другие данные, которые являются уникальными для этого элемента, и почему вы не должны использовать такие вещи, как
Math.random()
.
Размещение атрибута key
на компонентах
Соглашение о том, что вы должны поместить атрибут key
к компоненту, является более подходящей практикой, поскольку, когда вы повторяете список и хотите отобразить элемент, это ясно указывает на то, что вы должны организовать этот код для отдельного компонента.
Установка атрибута key
в цикле
Заявление, которое вы указали в документах:
Ключ должен всегда предоставляться непосредственно компонентам в массиве, а не содержимому HTML-контейнера каждого компонента в массиве:
Означает, что если вы обрабатываете компоненты в цикле, тогда вы должны установить атрибут key
компонента в цикле, как вы это сделали в своем компоненте EventsTable
:
{this.props.list.map(function (row) {
return (
<Event key={row.WhatId} data={row} />
);
})}
Неправильный путь - передать его компоненту, где он установит key
сам по себе:
Event = React.createClass({
displayName: 'Event',
render() {
// Don't do this!
return (
<tr key={this.props.data.WhatId}>
{_.keys(this.props.data).map((x) => {
В этой статье есть еще один хороший пример этого .
Ответ 3
У меня тоже были проблемы, и я исправил его после ссылки .
как:
{_data.map(function(object, i){
return <div className={"row"} key={i}>
{[ object.name ,
<b className="fosfo" key={i}> {object.city} </b> , // remove the key
object.age
]}
</div>;
})}