In Dan Abramov blog post, I read
Note that the key is only relevant within a particular parent React element, such as a form. React won’t try to “match up” elements with the same keys between different parents.
So it says here:
let data = [0, 1];
return (
<div>
<div>
{data.map((x) => (
<span key={x}>{x}</span>
))}
</div>
<div>
{data.map((x) => (
<span key={x}>{x}</span> // has different parent but same keys
))}{" "}
</div>
</div>
);
React won't confuse the span elements even though they have same keys, because they belong to different parents.
But how would React differentiate, for example, such case?
let data = [0, 1];
return (
<div>
<span key={0}>0</span>
{data.map((x) => (
<span key={x}>{x}</span>
))}
{data.map((x) => (
<span key={x}>{x}</span>
))}
</div>
);
Would reconciliation work correctly in this case? How?
Because above thing would translate to something like:
<div>
<span key="0">0</span>
<span key="0">0</span>
<span key="1">1</span>
<span key="0">0</span>
<span key="1">1</span>
</div>
But I don't get any warning with above code, so seems React is able to do Reconciliation correctly still.
I have no definitive proof but I don't think this case is missing a warning. I rather suppose React does something like React.Children.toArray when encountering an array of children:
React.Children.toArray() changes keys to preserve the semantics of nested arrays when flattening lists of children. That is, toArray prefixes each key in the returned array so that each element’s key is scoped to the input array containing it.
So my guess would be that reconciliation works here.
Additionally, I personally would implement an "duplicate key" check in a late rendering stage, so that all edge cases (including your example) are catched. There's no warning, so that's IMO a strong clue that there are no duplicate keys.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With