What is the prop "key" for in React?

Asked

Viewed 122 times

5

When rendering a dynamic list in React or React Native, I receive the following warning:

Warning: Each Child in a list should have a Unique "key" prop.

Despite this, things seem to work well without the prop key. Behold this example:

function shuffleArray(array) {
  var currentIndex = array.length,
    randomIndex;

  // While there remain elements to shuffle...
  while (0 !== currentIndex) {
    // Pick a remaining element...
    randomIndex = Math.floor(Math.random() * currentIndex);
    currentIndex--;

    // And swap it with the current element.
    [array[currentIndex], array[randomIndex]] = [
      array[randomIndex],
      array[currentIndex]
    ];
  }

  return array;
}

function App() {
  const [pokemons, setPokemons] = React.useState([
    {
      name: "Bulbasaur",
      img: "https://assets.pokemon.com/assets/cms2/img/pokedex/detail/001.png"
    },
    {
      name: "Ivysaur",
      img: "https://assets.pokemon.com/assets/cms2/img/pokedex/detail/002.png"
    },
    {
      name: "Venusaur",
      img: "https://assets.pokemon.com/assets/cms2/img/pokedex/detail/003.png"
    },
    {
      name: "Charmander",
      img: "https://assets.pokemon.com/assets/cms2/img/pokedex/detail/004.png"
    },
    {
      name: "Charmeleon",
      img: "https://assets.pokemon.com/assets/cms2/img/pokedex/detail/005.png"
    },
    {
      name: "Charizard",
      img: "https://assets.pokemon.com/assets/cms2/img/pokedex/detail/006.png"
    },
    {
      name: "Squirtle",
      img: "https://assets.pokemon.com/assets/cms2/img/pokedex/detail/007.png"
    },
    {
      name: "Wartortle",
      img: "https://assets.pokemon.com/assets/cms2/img/pokedex/detail/008.png"
    },
    {
      name: "Blastoise",
      img: "https://assets.pokemon.com/assets/cms2/img/pokedex/detail/009.png"
    }
  ]);

  function shuffle() {
    setPokemons(shuffleArray([...pokemons]));
  }

  return (
    <ul>
      <button onClick={shuffle}>Embaralhar</button>
      {pokemons.map((pokemon) => (
        <li onClick={() => console.log(pokemon.name)}>
          <img src={pokemon.img} alt={pokemon.name} />
          <span>{pokemon.name}</span>
        </li>
      ))}
    </ul>
  );
}

ReactDOM.render(<App /> , document.querySelector("#app"));
ul {
  padding-right: 2rem;
  padding-left: 2rem;
}

li {
  list-style: none;
  display: flex;
  align-items: center;
  padding: 10px;
  border: 2px solid #ccc;
}

li:hover {
  background-color: #deebff;
  cursor: pointer;
}

img {
  height: 40px;
  width: 40px;
}

span {
  font-size: 20px;
}
<script crossorigin src="https://unpkg.com/react@17/umd/react.production.min.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@17/umd/react-dom.production.min.js"></script>
<div id="app"></div>

To resolve this warning, I have found several answers here using the index as key, then I have the following doubts:

  • What is this property for key?

  • I need to define a key just walking through an array?

  • How can I define a key? Can I use the index, a random number or have another better way?

  • 2

    Before the answers come, I want to make it clear that the goal here is to create a canonical question, not just solve the warning. Thus, this question can be referenced when this problem is noticed in another question of the site (as I have seen several times).

  • Are the motives the same as Angular and Vuejs? If so, perhaps it would be better to remove the word React? Since the intention is to create a canonical one.

  • @Danizavtz, in this case I think it would be better to have a canonical one for each library (or framework, hehe), since each one can have its respective peculiarities, so that it can get confusing to do everything in one answer. : -) But of course this is for the AP to decide.

  • @Danizavtz what are the reasons to use in angular and vuejs?

  • Rafael Tavares the answer given by me lacks something?

  • @novic Your answer is good, I even voted for it. If you want to leave it complete, I think you could mention the reason for the key impact performance (I explained briefly here), This would also explain why there were unexpected behaviors that you mentioned; and I think there was a lack of clarification when you can use indexes as a key. For example, a list generated from an array that does not change the order, nor inserts items in the beginning/middle and nor removes, has no problems using the index, the reason is explained in the answer that Linkei.

  • @novic Rereading my answer, I saw that it is important to mention also the danger in the use of unstable keys, as the Math.random() or new Date()

  • @Leobrescia is related but does not answer. It answers (more or less) only to the second point (I need to define a key only when traversing an array?), and only answers this because of the answer, the question is misspelled and just wants to solve the error.

Show 4 more comments

1 answer

6

What is this property for key

To uniquely identify each element or component that will be created, modified, deleted and/or selected from a list of values (array), that is, is linked to the creation of dynamic elements of any list that need to have uniqueness.

I need to define a key only while walking a array?

Actually the correct question: When using a array to create dynamic elements you need to use a unique identifier (key)?

Yes, when creating an element or component it is necessary to pass an identifier so that the React knew which elements were created, changed, deleted and/or selected.

Generally speaking it’s like React checks the modifications in its elements exactly so that in the end the performance is not compromised, but, it is not only that that makes the React perform better, there are more techniques for this to happen.

The exception to the question is that key is only used in the creation of dynamic elements from a array. A array may have other purposes such as: filters, creating new arrays and at that time not using key of the component.

How can I define a key? Can I use the index, a random number or have another better way?

It is not ideal to use the index of a array to identify the elements or components and the predominant reason is that changes can occur in the ordering of these values (which encompass any change in this array such as insertions of new values, list item deletions and order changes) that can impact performance and rendering unnecessarily, causing slowness and errors. If your list does not suffer any of these actions cited can even use the index of array as a oneness (particularly prefer not to use), for example, a list of values display that does not undergo any modification and will only serve as a display.

In a list the items have a unique identification as for example id of a database table or some repository is very recommended to use it, another way is to use codes in ready packages such as uniqueid and nanoid, also generating in this case a full identification of each element.

Do not use codes that may cause or have a chance of causing duplicity and thereby breaking the main reason the key exists to identify which element has been modified.

References

Browser other questions tagged

You are not signed in. Login or sign up in order to post.