Подтвердить что ты не робот

Получение предупреждения о ключевой опоре в Реактите, даже если задан ключ

Проблема

Я получаю это предупреждение:

Предупреждение: каждый дочерний элемент в массиве или итераторе должен иметь уникальную "ключевую" опору. Проверьте метод рендеринга 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-контейнера каждого компонента в массиве:

Я сильно смущен. Почему я получаю предупреждения?

4b9b3361

Ответ 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>; 
})}