Getting key prop warning in React, even though key is set

前端 未结 5 1319
死守一世寂寞
死守一世寂寞 2021-01-07 16:29

Problem

I\'m getting this warning:

Warning: Each child in an array or iterator should have a unique \"key\" prop. Check the render method of

相关标签:
5条回答
  • 2021-01-07 17:13

    Have you tried adding a key to the <th> tag?

             <tr>
                {_.keys(this.props.list[0]).map(function (key) {
                  if (key !== 'attributes') {
                    return <th key={key}>{key}</th>;
                  }
                })}
             </tr>
    
    0 讨论(0)
  • 2021-01-07 17:16

    Check if variable that you pass to key is defined, because if it's undefined then error will be same, but it looks like code should work.

    0 讨论(0)
  • 2021-01-07 17:19

    I realize this thread is pretty old, but I was just having this issue and it was driving me crazy. I ended up solving it when I realized because I had a <React.Fragment> which also needs a unique key.

    0 讨论(0)
  • 2021-01-07 17:25

    I had the problems too, and fixed it after follwing link.

    like:

    {_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>; 
    })}
    
    0 讨论(0)
  • 2021-01-07 17:34

    tl;dr

    Every time you render a list (use map), add a unique key attribute to the list elements (the topmost or "root" element returned from map's callback):

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

    Explanation

    Understanding keys in React

    The official Lists and Keys documentation shows how you should work with lists and the linked reconciliations doc tells the whys.

    Basically when React rerenders a component it runs a diff algorithm that finds out what changed between the new and the previous version of the list. Comparison is not always trivial, but if there is a unique key in each element, it can be clearly identified what has changed. See the example in the doc:

    <!-- 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>
    

    It is clear that a new element with the key 2014 was added, since we have all the other keys and those weren't changed. Without the keys this would be obscure.

    Selecting a proper key

    From now it is easy to see:

    • Why it is important that the key should be unique but only between the siblings in the list, because the comparison happens only within the given list's previous and new elements.
    • The key should remain the same for the same element between the previous and the new version, otherwise we would compare different elements and wouldn't be able to track change. That is why it is advised to use the id of the resource or (if it doesn't have one) some other data that is unique to the element, and why you shouldn't use things like Math.random().

    Placing key attribute on components

    The convention that you should place the key attribute to a component is more of a good practice, because when you iterate a list and want to render an element, that clearly indicates that you should organize that code to a separate component.

    Setting the key attribute in the loop

    The statement you quoted from the docs:

    The key should always be supplied directly to the components in the array, not to the container HTML child of each component in the array:

    Means that if you render components in a loop, then you should set the key attribute of the component in the loop, like you did it in your EventsTable component:

    {this.props.list.map(function (row) {
      return (
        <Event key={row.WhatId} data={row} />
      );
    })}
    

    The wrong way is to pass it down to the component where it would set the key on itself:

    Event = React.createClass({
      displayName: 'Event',
      render() {
        // Don't do this!
        return (
          <tr key={this.props.data.WhatId}>
            {_.keys(this.props.data).map((x) => {
    

    There is another good example for this in this article.

    0 讨论(0)
提交回复
热议问题