Home > Enterprise >  Is there any difference between key={i} and key={`foo-${i}`}?
Is there any difference between key={i} and key={`foo-${i}`}?

Time:11-30

I'm reading an advanced React book called React Cookbook. For some reason, the author uses a key with prefix, like this:

<div>
    {state.items.map((s, i) => (
        <div key={`square-${i}`}>
            {s}
        </div>
    ))}
</div>

I keep seeing key constructed that way and it always surprises me, especially from an advanced author. As far as I know, there is no difference between this and just key={i}.

When I started with React, I had some less advanced React devs telling me that this is useful when you nest lists, like this:

<div>
    {state.items.map((s, i) => (
        <div key={`square-${i}`}>
            {s.map(f, j) => (
                <div key={`foo-${j}`}>
                    {f}
                </div>
            )}
        </div>
    ))}
</div>

But, this is also useless, since key uniqueness is scoped, right? So the keys at different levels or different lists don't need to be unique.

Perhaps there would be some sense in doing that if my list consisted of two or more kinds of things, like this:

<div key={`${item.type}-${i}`}>

But other that this, why would someone use index-based key in shape of anything else that just the index?

CodePudding user response:

I believe people started adding the prefixes because they incorrectly assumed how uniqueness worked across the tree:

Keys are scoped to a sibling level. You can have the same key up/down the component tree but not sideways. Beware though this is not directly related to the DOM tree itself, but to react component tree.

An array-type react child has a "parent" so keys can be repeated across "siblings" (technically not siblings since they have this "array parent", which is transparent in the DOM tree).

The following code is valid and doesn't trigger any warnings. The related react-dom code can be found here.

    <parent key="unique">
      <sibling key="must" />
      <sibling key="be" />
      <sibling key="unique">
        <child key="unique" />
      </sibling>
    </parent>
  <div>
    {['a', 'b', 'c', 'd', 'e'].map((letter, idx) => (
      <span key={idx}>{letter}</span>
    ))}
    {['a', 'b', 'c', 'd', 'e'].map((letter, idx) => (
      <span key={idx}>{letter}</span>
    ))}
  </div>

Using the index as key approach is perfectly fine and safe if the data is "static" and won't ever change, otherwise you may have render issues and/or a performance hit.

CodePudding user response:

Using foo-${i} instead of i is redundant and behaves the same.

Because, Indexes are not recommended for key props, regardless of whether they are used alone or in string interpolations.

While the prefix does not change, the index will change whenever the item is being added or deleted from the array, and foo-0 is NOT equal to foo-1. In such cases, react will re-render the item because the previous key prop does not match the new one.

CodePudding user response:

Using an index for the key is not recommended by react official documentation if your list data order might change. I think the author know this and create prefix for the key so it become string and not mere number. Check docs for key here

  • Related