You shouldn't use an index as key of the element

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 <Row>, 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 😂.

Comments (1)

fengxh's photo

It is exactly the problem. I always pass the id or code field as key in React/Vue.

shortedRow.map(data => <Component key={data.id}  />)