Home > Software engineering >  Do keys in separate loops still need to be unique among siblings?
Do keys in separate loops still need to be unique among siblings?

Time:12-08

I was wondering how does the key work in loops. Do they create a separate branch, or do they still need to be unique for the same parent? This is what I'm talking about:

// This is obviously an error:
<div>
    <div key="gimme-a-break" />
    <div key="gimme-a-break" />
</div>

// This is an error too:
<div>
    {<div key="gimme-a-break" />}
    {<div key="gimme-a-break" />}
</div>

// Still an error:
<div>
    {(() => <div key="gimme-a-break" />)()}
    {(() => <div key="gimme-a-break" />)()}
</div>

// But, surprisingly, this is fine:
<div>
    {["boo"].map(() => <div key="gimme-a-break" />)}
    {["boo"].map(() => <div key="gimme-a-break" />)}
</div>

Is it just that React's parser can't figure out that the keys are duplicated, or do they indeed got separate context in the last example?

The official documentation says:

Keys used within arrays should be unique among their siblings. However, they don’t need to be globally unique. We can use the same keys when we produce two different arrays.

But this is not clear whether the separate loops creating siblings for the same parent need to have unique keys too or not.

Is there some source explaining how it works?

CodePudding user response:

An array type is a valid React child (more correctly an array of React nodes);

The keys hint applies to React nodes of array type.

For validation, refer to next babel JSX transform and React.createElement API (third arg is children array):

const Component = () => {
  return (
    <>
      {[<div key="gimme-a-break" />, <div key="gimme-a-break" />]}
    </>
  );
};


// Transforms to
"use strict";

const Component = () => {
  return /*#__PURE__*/React.createElement(React.Fragment, null, [/*#__PURE__*/React.createElement("div", {
    key: "gimme-a-break"
  }), /*#__PURE__*/React.createElement("div", {
    key: "gimme-a-break"
  })]);
};

// Hint, you can check this transform, but might be more confusing
const Component2 = () => {
  return (
    [<div key="gimme-a-break" />, <div key="gimme-a-break" />]
  );
};
  • Related