All about React key

Concepts that are overused can't escape abuse. In fact when concepts are overused, they usually are not well understood by the multitude who use them except for some few. The same is with React key.

If you are a react developer (sorry I'm presuming you are not), the key props isn't a new word. You must have seen it been used when implementing list of elements or mapping over arrays in your favourite react books/articles, or most likely Eslint error screamed at your code in the console or whatever other place when you were mapping an array. My point is the key props isn't new per se.

Yes it isn't?

Next permit me to ask you the question "why do we use the key props?" or perhaps a better grammar is "what does the key props helps with in react?". Haahaa, for majority of developers the answer is most likely "well, it is used on list of elements to identify and differentiate them" or PERHAAAAPS "it is important when re-rendering list of elements in react".

Whatever your answer was it is probably almost right. The objectives of the next few coming paragraphs are to enlighten US, yes us, on what the react key is, some of the problems with using it and places you should visit if the goal is to learn more in-depth.

Waawuu!! Now to business:

Why we use the key attribute in react?

The react key is a prop or better still an attribute for react components that helps identify element of the same type among it siblings. Permit me to quote NADIA MAKAREVICH in his blockbuster article who defined it as "The attribute that React uses as a way to identify an element of the same type among its siblings during re-renders".

Why do react complain when I skip the key attribute?

Sincerely I do not understand why. When you skip key attribute, React does the dirty job of adding the key in there with the indexes of each siblings. So why screaming when you've done the job for me?

I hope you got the joke LOL. What it means is react hates to do the dirty job. So let's write it out with our bold chest anyways.

// ex-1

whatevers.map((whatever, index)=> <Item payload={whatever} key={index} />)

React can at least shut up the screaming error.

Hollop, remember when you skipped the key attribute and react was screaming, React defaults to using indexes like we did in ex-1. It does this under the hood.

If react does it this way under the hood, why the screaming error? That leads to the revelation that although the use of index work fine it isn't best for all cases.

Best cases to use the index

If you are sure your lists won't be changing for any reason, the use of index as in case ex-1 is just fine. But if your list would be changing (eg contrasting, expanding generally activities that would manipulate your list, then there is a need for a rethink.

DONOT USE UNIQUE KEYS except it is already predefined

Well that is coming with a threat too.

ex-2
whatevers.map((whatever, index)=> <Item payload={whatever} key={Math.random()} />)

Please this is a disaster. If you are curious the next question would have been why? Cases where the unique string isn't already defined would cause not just re-renders but mounting and unmounting of the element since the key prop would never be the same even if your list won't be changing or no manipulation would be done on it.

const lists = [
  {name: 'sekx'},
  {name: 'Kelvin'}
]

function App (){
  const [, forceRender] = React.useState()

  React.useEffect(
    function addOnClickHandlerToWindow(){
      window.addEventListener('click', forceRender)
      return ()=>window.removeEventListener('click', forceRender)
   }, []
  )

return <div>
   {lists.map(list=> <Item 
    payload={list} 
    key={Math.random()} 
    />)}
</div>
}

const Item = React.memo(function Item ({payload}) {
console.log('render') // a cue to see when this components re-renders in your console
return <p>{payload.name}</p>
})

Oops! I just introduced React.memo, let me rush that - it compares the prevProps and nextProps - If it was for me, I would have called it presentProps and not nextProps -, shallow comparison though, if no changes, it doesn't re-render the returned element and uses the already mounted one.

That was quick, my point here is even with the memo thingi, the list will always re-render if you try clicking anywhere on the browser window. If you replace the Math.random() part with index like it is done in ex-1, and you try clicking anywhere on the screen, it won't re-render LOL.

Well I just came with a big threat and justified it - NEVER USE A UNIQUE KEY. You must always define it or use the index.

Because I am always in a rush, I need to talk about the last case. If your list would be manipulated at any point in the app, please do not use index. Instead use a predefined key value like I did below.

const lists = [
        {name: 'sekx'},
        {name: 'Kelvin'}
]

function App (){
  const [newlist, setList] = React.useState(lists)

  return (
  <div>
     <button
       onClick={()=> setList(newlist.slice().reverse())}
     >reverse</button>
    <div>
      {newlist.map(each => <Item payload={each} key={each.name} />)}  {/** line-12*/}
    </div>
  </div>
)
}

const Item = React.memo(function Item({ payload }) {
console.log('render')
  return <p>{payload.name}</p>;
});

If you change the key in line-12 to use indexes like we did in ex-1, you would see in the console that the Item component re-renders for every click on the reverse button.

Our aim is to always maximize re-renders and unmounting as a react guru that you are.

Thanks for reading thus far. I really hope this short and quick brush on react key helps you going forward. Bye!!!!!!!

If you would love to read more and get more intensified examples. Please read