0

I encountered a duplicate key warning that I did not expect(because it's not a list of the same type of components) for the following:

<Foo key={'baz'} />
<Bar key={'baz'} />
  1. Why it's totally fine to have the following?
<Foo />
<Bar />
  1. Why it's problematic for the react fiber to consider component type when handling key uniqueness?
  2. Could this be because there is some advanced use case where a developer might want to have the same key for different types of components?

It's all clear regarding keys and lists, just curious how it works under the hood.

gromaco
  • 11
  • 1
  • Why are you reusing the same key, aren't they treated like id attributes? – Mr. Polywhirl Apr 28 '23 at 11:59
  • It's because he believed react is (and is wondering why it doesn't) creating a compound key internally of the `key` string and the component type. – adsy Apr 28 '23 at 12:00
  • If they are siblings, they are still children of another parent element. So they are still technically children. This would trigger a: `Warning: Each child in a list should have a unique “key” prop.` – Mr. Polywhirl Apr 28 '23 at 12:02
  • Yes. Agree with @Mr.Polywhirl even if your siblings doesn't look like you you are still siblings and have the same connection with your parents. – Alison Henrique Jonck Apr 28 '23 at 12:02
  • Yeh, correct. He knows that I think. He's wondering how come react doesn't take component type into account in its uniqueness heuristics. It doesn't, but he wants to know why. – adsy Apr 28 '23 at 12:03
  • @adsy I assume, for internal selector purposes, that they should be unique; because the element type or tag name doesn't really matter in the grand scheme of things. – Mr. Polywhirl Apr 28 '23 at 12:04
  • I don't think it would have been a good idea, but theoretically, react devs could have chosen to internally generate a tuple key, containing the user provided key and the component type. If it did that, then his code would work. It would be very weird semantics though I think and more confusing than useful. Especially around conditional logic for component types one might have. It would also be surprising and just adding another weird edge for no big gain. – adsy Apr 28 '23 at 12:05
  • Does this answer your question? [Understanding unique keys for array children in React.js](https://stackoverflow.com/questions/28329382/understanding-unique-keys-for-array-children-in-react-js). See [Chris' response](https://stackoverflow.com/a/43892905/1762224). – Mr. Polywhirl Apr 28 '23 at 12:07
  • @adsy is totally correct in terms of the root of my question. Also, the confusing part for me is why we get a warning when we don't set keys in the explicit list of components, but we don't get warnings for regular siblings until we set the duplicated key? – gromaco Apr 28 '23 at 12:25

2 Answers2

2

If they are siblings, they are still children of another parent element. So they are still technically children.

This would trigger a: Warning: Each child in a list should have a unique “key” prop.

const Foo = () => <div>Foo</div>
const Bar = () => <div>Bar</div>

const App = () => {
  return (
    <React.Fragment>
      <Foo key="baz" />
      <Bar key="baz" />
    </React.Fragment>
  );
};

ReactDOM
  .createRoot(document.getElementById("root"))
  .render(<App />);
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.development.js"></script>

As expected, we are presented with the following error:

Warning: Encountered two children with the same key, baz. Keys should be unique so that components maintain their identity across updates. Non-unique keys may cause children to be duplicated and/or omitted — the behavior is unsupported and could change in a future version.

Chris' response to "Understanding unique keys for array children in React.js" explains all you need to know about they key prop.

He cites the React docs:

Keys Must Only Be Unique Among Siblings

Keys used within arrays should be unique among their siblings. However, they don’t need to be globally unique.

In conclusion, since they are siblings (disregarding component type), each key prop should be unique.


Since we can re-use keys (non-global), we can actually do the following:

const MyComponent = () => (
  <div>
    <div key="a">a</div>      {/* Local, will be rendered n-number of times */}
    <a key="b" href="#">b</a> {/* Same as above... */}
  </div>
)
const App = () => {
  return (
    <React.Fragment>
      <MyComponent key="foo" /> {/* Will render 'a' and 'b' */}
      <MyComponent key="bar" /> {/* Will render 'a' and 'b' */}
    </React.Fragment>
  );
};

ReactDOM
  .createRoot(document.getElementById("root"))
  .render(<App />);
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.development.js"></script>

Note: Keep in mind that you should only have to supply a key when mapping over an array of items.

Mr. Polywhirl
  • 42,981
  • 12
  • 84
  • 132
  • This doesn't answer my question - why it's problematic to have a compound key that considers a component type? And it doesn't explain why we get a warning when we don't set keys in the explicit list of components, but we don't get warnings for regular siblings until we set the duplicated key. – gromaco Apr 28 '23 at 12:45
  • @gromaco keys are optional, unless you are looping over data and rendering a list. – Mr. Polywhirl Apr 28 '23 at 13:12
  • They are. Thanks for your comment. But that's not part of my question. "It's all clear regarding keys and lists, just curious how it works under the hood." I'll try to rephrase the question from my prev comment(https://stackoverflow.com/questions/76129329/react-keys-for-sibling-components-of-different-types/76129386#comment134258729_76129489) - what is the essential difference between regular siblings and components in the loop? And why not use compound keys? No need to repeat the same info from the docs. I'm not asking if keys are needed when we render an array of elements. – gromaco Apr 28 '23 at 14:10
0

I think it doesn't matter which component type you would use.

Consider the following code:

<>
 <button key="1"> Test1 </button>
 <div key="2">
   <span> Test22 </span>
 </div>
 <p key="3"> Test333 </p>
</>

If you are iterating in order to create that you will get warnings to provide unique keys for each node inside the parent node.

  • But why it's totally fine to omit keys when I'm not iterating? It's a vary simple function that handles keys(if that's the right function) - https://github.com/facebook/react/blob/main/packages/react/src/ReactChildren.js#L63 – gromaco Apr 28 '23 at 12:12