About Me
Blog

React Keys and ReactDOM

August 17, 2021

2 min read


Keys help identify React Components

Traditionally when we are taught about keys in React, it is in the context of rendering a list of elements. Take this simple example:

let users = [...] // some array of users
...
users.map(user => <User name={user.name} />)

When rendering this array of <User> components, React has no way of telling each of the elements apart in the array. The key uniquely identifies each component, so React can uniquely track the component across re-renders.

users.map(user => <User key={user.id} name={user.name} />)

Index != a good key

Now, if we don’t specify a key, then the only information React has to identify a specific element is its index in the array. So React will use the index as the key.

// no key specified
users.map(user => <User name={user.name} />)
// being explicit
users.map((user, index) => <User key={index} name={user.name} />)

Why is this a bad idea? Well the requirements of the key are to:

  • uniquely identify a component
  • stay the same across re-renders (so React can track the component)

Using an index as a key only works only if you fix the indices for each of the elements, that is the array stays the same. If you change the order, or add / remove elements from the array, you can get weird bugs, because now the index doesn’t fit the requirements of a valid key.

E.g. say we have an array of <User> components, each with their own state about that user. React tells them apart by their position in the array, so when it comes to looking up state it will find the user state associated with that position.

See the issue? It’s associated by position (the key) not the component.

So if I add a new user to the start of the array, then every user shifts along one in the array.

;[<User name="Bob" />, <User name="Charlie" />][
// add Alice
((<User name="Alice" />), (<User name="Bob" />), (<User name="Charlie" />))
]

In the example above, Alice slots into Bob’s position so inherits the state associated with Bob! Oh dear.

Using Keys to force a re-render

Keys aren’t limited to components in a collection (like an array), in fact every component has an implicit key associated with it that React uses to track it. Theres’s a 1:1 mapping from keys to components. So different key => different component!

We can thus force the ReactDOM to re-render by changing the key of a component. When the key changes, React realises that this is no longer the same component and thus resets the state. So in my website for example, I can get React to re-render whenever the active tab changes.

<TabSection key={activeTab} />

Note the difference between key and props, if I had passed the value in via props, e.g. props.tab, then React would have re-rendered the same TabSection component, whereas passing in as key re-renders with another TabSection component associated with the new key.

<TabSection tab={activeTab} />

In essence we’re tracking multiple TabSection components, one for each of values activeTab can take, and each with completely independent state.

Share This On Twitter

If you liked this post, please consider sharing it with your network. If you have any questions, tweet away and I’ll answer :) I also tweet when new posts drop!

PS: I also share helpful tips and links as I'm learning - so you get them well before they make their way into a post!

Mukul Rathi
© Mukul Rathi 2021