Понимание уникальных ключей для детей массива в React.js



Я создаю компонент React, который принимает источник данных JSON и создает сортируемую таблицу.

Каждая из динамических строк данных имеет уникальный ключ, назначенный ему, но я все еще получаю ошибку:




каждый ребенок в массиве должен иметь уникальный" ключ " опоры.

Проверьте метод рендеринга TableComponent.




мой TableComponent рендер метод возвращает:



<table>
<thead key="thead">
<TableHeader columns={columnNames}/>
</thead>
<tbody key="tbody">
{ rows }
</tbody>
</table>


The 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>
)
}
});


что вызывает ошибку уникального ключа prop?

872   7  

7 ответов:

вы должны добавить ключ к каждому ребенку а также каждый элемент внутри детей.

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

в вашем коде, каждый <TableRowItem key={item.id} data={item} columns={columnNames}/> пытается сделать некоторые дети в них без ключа.

Регистрация .

Попробуйте удалить key={i} С <b></b> элемент внутри div (и проверьте консоль).

в образце, если мы не даем ключ к <b> элемент и мы хотим обновить только the object.city, React необходимо повторно отобразить всю строку против только элемента.

вот код:

var data = [{name:'Jhon', age:28, city:'HO'},
            {name:'Onhj', age:82, city:'HN'},
            {name:'Nohj', age:41, city:'IT'}
           ];

var Hello = React.createClass({

    render: function() {

      var _data = this.props.info;
      console.log(_data);
      return(
        <div>
            {_data.map(function(object, i){
               return <div className={"row"} key={i}> 
                          {[ object.name ,
                             // remove the key
                             <b className="fosfo" key={i}> {object.city} </b> , 
                             object.age
                          ]}
                      </div>; 
             })}
        </div>
       );
    }
});

React.render(<Hello info={data} />, document.body);

реагировать документация о важности ключей в согласовании:ключи

будьте осторожны при итерации по массивам!!

это распространенное заблуждение, что использование индекса элемента в массиве является приемлемым способом подавления ошибки, с которой вы, вероятно, знакомы:

Each child in an array should have a unique "key" prop.

однако, во многих случаях это не так! Это анти-шаблон, что в некоторые ситуации приводят к нежелательное поведение.


понимание элемент key prop

React использует key prop, чтобы понять отношение элемента component-to-DOM, которое затем используется для процесс примирения. Поэтому очень важно, чтобы ключ всегда остается уникальный, в противном случае есть хороший шанс, что React смешает элементы и мутирует неправильный. Также важно, чтобы эти ключи остаются статичными на протяжении всего ре-рендеринга для того, чтобы поддержите самое лучшее представление.

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

разработчик React сказал в эта проблема GitHub:

  • ключ на самом деле не о производительности, это больше о личности (что в свою очередь приводит к более высокой производительности). случайно назначенные и изменяющиеся значения не являются идентичностью
  • мы не можем реально предоставить ключи [автоматически], не зная, как моделируются ваши данные. Я бы предложил, возможно, использовать какую-то функцию хэширования, если у вас нет идентификаторов
  • у нас уже есть внутренние ключи, когда мы используем массивы, но их индекс в массиве. Когда вы вставляете новый элемент, эти ключи неверны.

короче говоря, a key должны быть:

  • уникальный - ключ не может быть идентична sibling component.
  • Static - ключ никогда не должен меняться между рендерами.


С помощью key prop

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


плохо (Потенциально)

<tbody>
    {rows.map((row, i) => {
        return <ObjectRow key={i} />;
    })}
</tbody>

это, пожалуй, самая распространенная ошибка, наблюдаемая при итерации по массиву в React. Этот подход не является технически "неправильные", это просто... "опасные" если вы не знаете, что вы делаете. Если вы повторяете через статический массив, то это совершенно правильный подход (например, массив ссылок в меню навигации). Однако, если вы добавляете, удаляете, переупорядочиваете или фильтруете элементы, то вам нужно быть осторожный. Взгляните на это подробное объяснение в официальной документации.

class MyApp extends React.Component {
  constructor() {
    super();
    this.state = {
      arr: ["Item 1"]
    }
  }
  
  click = () => {
    this.setState({
      arr: ['Item ' + (this.state.arr.length+1)].concat(this.state.arr),
    });
  }
  
  render() {
    return(
      <div>
        <button onClick={this.click}>Add</button>
        <ul>
          {this.state.arr.map(
            (item, i) => <Item key={i} text={"Item " + i}>{item + " "}</Item>
          )}
        </ul>
      </div>
    );
  }
}

const Item = (props) => {
  return (
    <li>
      <label>{props.children}</label>
      <input value={props.text} />
    </li>
  );
}

ReactDOM.render(<MyApp />, document.getElementById("app"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app"></div>

в этом фрагменте мы используем нестатический массив, и мы не ограничиваемся его использованием в качестве стека. Это небезопасный подход (вы увидите, почему). Обратите внимание, как при добавлении элементов в начало массива (в основном unshift), значение для каждого <input> остается на месте. Зачем? Потому что key не идентифицирует однозначно каждый элемент.

другими словами, сначала Item 1 и key={0}. Когда мы добавляем второй элемент, верхний элемент становится Item 2, следовал по Item 1 как второй пункт. Однако теперь Item 1 и key={1}, а не

предупреждение: каждый дочерний элемент в массиве или итераторе должен иметь уникальный" ключ " prop.

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

React обрабатывает итерационный рендеринг компонентов в виде массивов.

лучший способ решить эту проблему-предоставить индекс для элементов массива, которые вы собираетесь перебирать.например:

class UsersState extends Component
    {
        state = {
            users: [
                {name:"shashank", age:20},
                {name:"vardan", age:30},
                {name:"somya", age:40}
            ]
        }
    render()
        {
            return(
                    <div>
                        {
                            this.state.users.map((user, index)=>{
                                return <UserState key={index} age={user.age}>{user.name}</UserState>
                            })
                        }
                    </div>
                )
        }

индекс реагирует встроенный реквизит.

просто добавить уникальный ключ к вашим компонентам

data.map((marker)=>{
    return(
        <YourComponents 
            key={data.id}     // <----- unique key
        />
    );
})

я исправил это с помощью Guid для каждого ключа, как это: Генерация Guid:

guid() {
    return this.s4() + this.s4() + '-' + this.s4() + '-' + this.s4() + '-' +
        this.s4() + '-' + this.s4() + this.s4() + this.s4();
}

s4() {
    return Math.floor((1 + Math.random()) * 0x10000)
        .toString(16)
        .substring(1);
}

и затем присвоение этого значения маркерам:

{this.state.markers.map(marker => (
              <MapView.Marker
                  key={this.guid()}
                  coordinate={marker.coordinates}
                  title={marker.title}
              />
          ))}

Пример: Правильное Использование Ключа

function ListItem(props) {
  // Correct! There is no need to specify the key here:
  return <li>{props.value}</li>;
}

function NumberList(props) {
  const numbers = props.numbers;
  const listItems = numbers.map((number) =>
    // Correct! Key should be specified inside the array.
    <ListItem key={number.toString()}
              value={number} />

  );
  return (
    <ul>
      {listItems}
    </ul>
  );
}

const numbers = [1, 2, 3, 4, 5];
ReactDOM.render(
  <NumberList numbers={numbers} />,
  document.getElementById('root')
);

это предупреждение, но адресация это сделает реагирует рендеринг намного быстрее,

это так React необходимо однозначно идентифицировать каждый элемент в списке. Допустим, если состояние элемента этого списка изменяется в Reacts Virtual DOM затем React должен выяснить, какой элемент был изменен и где в DOM он должен измениться, чтобы браузер DOM был синхронизирован с виртуальным DOM Reacts.

как решение просто представьте себе key атрибут для каждого li - тег. Это key должно быть уникальное значение для каждого элемента.

Comments

    Ничего не найдено.