Photo by ThisisEngineering RAEng on Unsplash
Let me brief you about discussion, in React or any other stack when we need to present line of code with records of an array we use either foreach, map or for a loop. And when we do that it's good to have assigned unique key to individual component/element. As shown in an example below --
const array = ["A", "B", "C", "D"];
array.map((element, index) => { // in secound parameter return current index of record
return `<li key=${index}> //defining key as attribute to line element
${ element }
<li>` //string concatination in js
})
You can read more on the map function here.
As you have seen in snippet we have defined index in key because key have a basic rule that it should be unique and most of the developers pass index as it'll be always unique. That's correct if you are thinking that way too.
But I faced one issue recently in react development by doing it. Let me share it with you...
- I created one react pure component (so, it won't rerender without props change) called , with height as props.
- I used it into the map under by table component.
- Table component:-
const rows = [30, 60, 40, 10] // starting point of row respective to table's starting point
const shortedRow = shortArray(rows) // shorting before use, value will be [10, 30, 40, 60]
return (
<Table>
{shortedRow.map((row, index) => <Row height={row} key={`row-${index}`}>)} // tried to use string with index as well
</Table>
<AddRowBtn addHeightAt={35} >
)
- Had add row btn at below, to add new row at given height in table
The problem I was facing:
As a given scenario, on the first load of an app, it'll work like a charm. Now as I add a new row with a height of 35, it'll update my 2nd and 3rd index with a new index at the end (like [10, 30, 35, 40, 60]).
While re-rendering, since my of 3rd row's height updated but the index is the same it didn't update in DOM. And I had distributed design in output.
What I did to resolve?: ###
Instead of passing an index in key, I started to pass a value(height) in key. so as soon as the height update element will re-render without doing anything. (this is one of the advantages of it too).
Current code looks like this:
const rows = [30, 60, 40, 10]
const shortedRow = shortArray(rows)
return (
<Table>
{shortedRow.map((row) => <Row height={row} key={`row-${row}`}>)} // tried to use string with height now
</Table>
<AddRowBtn addHeightAt={35} >
)
So, this was something new I figured recently. I thought to share it with you guys too. Hope this will help you, yes? then hit follow π.
Top comments (6)
Good article, you could also use a package like uuid() (npmjs.com/package/uuid) to generate a random unique key for you. This way you also avoid re-rendering if your amount of rows changes in this case, but it will create another dependency
That's a dangerous pattern to follow. I've been down that path, years ago. At worst, it can spawn some nasty bugs. At best, it's needlessly inefficient.
stackoverflow.com/questions/513719...
That is interesting, I think that in your example he is generating the unique key inside the map function, which will cause re-generating the keys for every re-render. If you put the unique key outside the loop function, e.g. as an object property, it should be fine:
medium.com/@robinpokorny/index-as-...
Solution can work, but same it will add dependency. But i think if we have any value unique in our array itself then we should just use it as key.
There is a brilliant article on this topic on the BlackRock Engineering blog.
This title is very misleading. Using an
index
is fine for most cases, but as you found, not all cases.