I'm learning React, and I stumbled upon this quirk with "dynamic children."
Preamble with a code example:
// Render Pass 1
<Card>
<p>Paragraph 1</p>
<p>Paragraph 2</p>
</Card>
// Render Pass 2
<Card>
<p>Paragraph 2</p>
</Card>
In the second render()
pass, it seems the way the vdom diffing works is that it deletes the second child, then transforms the text in the first to say "Paragraph 2." It's fast, but you'll see weird stuff happening if you needed state to persist on say... the second child!
So React suggests using a "key" attribute for those tags. Now the vdom diffing will be surprise-free and you'll see state getting preserved across renders()
.
My question: is there a way to get React to set "keys" on its own rather than doing it the way they suggest?
Use the Math. random() function to generate a random number in React, e.g. Math. floor(Math. random() * (max - min + 1)) + min .
You can set the component's name in the property displayName . If you're using ES6 classes, you can set a static property called displayName into component's class. Then, you'll be able to get the child name with child. type.
There are many ways in which you can create unique keys , the simplest method is to use the index when iterating arrays. var lists = this. state. lists.
Keys help React identify which items have changed, are added, or are removed. Keys should be given to the elements inside the array to give the elements a stable identity: const numbers = [1, 2, 3, 4, 5]; const listItems = numbers. map((number) => <li key={number.
No, there is not.
The default behavior of React when there are no keys specified is to use a naive approach updating components in-place, as you observed. Functionally, this is equivalent to specifying a default key according to the element's index with respect to its siblings. In your example, this would look like:
// Render Pass 1
<Card>
<p key={0}>Paragraph 1</p>
<p key={1}>Paragraph 2</p>
</Card>
// Render Pass 2
<Card>
<p key={0}>Paragraph 2</p>
</Card>
That's why you see the text for the first element transformed, but as you note this is not always the optimal outcome. So why can't React use a more intelligent automatic key? The answer is that in order to do so, there are really only two options, and neither is ideal:
They could make certain assumptions about the structure of your app. In your short example, it's obvious to a human that the paragraphs should be matched according to their text content. But that's not necessarily true in all cases, and it's hard to extend that kind of logic to more complex scenarios with custom elements, lots of props, nested children, etc.
They could use a fancy general-purpose diffing algorithm, but these can be quite costly in terms of performance which React is very conscientious of. As the React documentation on reconciliation says:
There are many algorithms that attempt to find the minimum sets of operations to transform a list of elements. Levenshtein distance can find the minimum using single element insertion, deletion and substitution in O(n2). Even if we were to use Levenshtein, this doesn't find when a node has moved into another position and algorithms to do that have much worse complexity.
So, either way, any benefit of "automatic key assignment" comes with a set of drawbacks as well. In the end, it's not really worth it, especially considering that in most cases assigning keys manually is not really that difficult or cumbersome. From further down on that same documentation page:
In practice, finding a key is not really hard. Most of the time, the element you are going to display already has a unique id. When that's not the case, you can add a new ID property to your model or hash some parts of the content to generate a key. Remember that the key only has to be unique among its siblings, not globally unique.
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