Using React's Key Attribute to remount a Component
Tags: react
Published: 2020-05-22 11:44:35

---
title: Using React's Key Attribute to remount a Component
published: true
description: First we checkout how React's key can be used, then walk through a real world scenario and finally discuss if we should use it.
tags: react
canonical_url: https://www.nikgraf.com/blog/using-reacts-key-attribute-to-remount-a-component
---

Usually we use React's special "key" string attribute only in combination with Lists. How and why is well explained in the React docs in the sections [Lists and Keys](https://reactjs.org/docs/lists-and-keys.html) and [Reconciliation - Keys](https://reactjs.org/docs/reconciliation.html#keys).

When you read through the Reconciliation docs you can find this explanation:

> When children have keys, React uses the key to match children in the original tree with children in the subsequent tree.

This doesn't really say what's happening when you change the key, but let's explore exactly that.

## Demo

We create a component `Item` with a `useEffect` logging out when the component mounts and unmounts. We achieve this with an empty dependency array.

```jsx
const Item = () => {
  useEffect(() => {
    console.log("Mount item");
    return () => console.log("Unmount item");
  }, []);
  return <div />;
};
```

In an `App` component we can use the `Item`. Every time you click on the button the string passed into `key` is updated.

```jsx
const App = () => {
  const [id, setId] = useState("123");
  return (
    <>
      <Item key={id} />
      <button onClick={() => setId(Math.random().toString())}>
        update
      </button>
    </>
  );
};
```

The result looks like this

![Remount example with console.log
  output](https://www.nikgraf.com/blog/using-reacts-key-attribute-to-remount-a-component/remount.gif)

That's quite interesting! By changing the key on a component we can force it to remount.

Here you can find a working [CodeSandbox example](https://codesandbox.io/s/sad-browser-bvpwk) and try it yourself.

## Real World Use Case

How is this even relevant? My main use-case so far was to force resetting the local state of a child in the component tree.

For example my team needed to render a list of items in a sidebar. Whenever you select an item, the main content shows a form to update each item.

![An example demo of the outcome](https://www.nikgraf.com/blog/using-reacts-key-attribute-to-remount-a-component/goal.gif)

Initially we built it in a way that a `Detail` component would have local state, which is based on the initial props. Let me illustrate this by a simplified example. Here the default value of `useState` is based on the prop `contact.name`.

```jsx
const Detail = (props) => {
  const [name, setName] = useState(props.contact.name);
  return (
    <form>
      <input
        value={name}
        onChange={(evt) => setName(evt.target.value)}
      />
    </form>
  );
};
```

Further prop changes would be ignored since `useState` will ignore them.

In our App component we included the `Detail` component like this:

```jsx
function App() {
  const [contacts, setContacts] = React.useState([
    { id: "a", name: "Anna" },
    { id: "b", name: "Max" },
    { id: "c", name: "Sarah" },
  ]);
  const [activeContactId, setActiveContactId] = React.useState(
    "a"
  );
  const activeContact = contacts.find(
    (entry) => entry.id === activeContactId
  );

  return (
    <>
      {contacts.map((contact) => (
        <button
          key={contact.id}
          onClick={() => setActiveContactId(contact.id)}
        >
          {contact.name}
        </button>
      ))}
      <Detail contact={activeContact} />
    </>
  );
}
```

In here whenever a user clicks on one of the buttons, the `Detail` component receives a new contact.
Sounded good until we realized the form actually never remounts.

![An example demo of the failing case](https://www.nikgraf.com/blog/using-reacts-key-attribute-to-remount-a-component/broken.gif)

It may seem obvious in hindsight, but initially this was our mental model: `switch contact -> component remounts`. With a deadline coming up soon, no one in the team was excited about restructuring the whole state. One of my colleagues discovered, that by adding the "key" attribute based on the item's id would allow us to achieve remounting the `Detail` component.

So we changed

```jsx
<Detail contact={activeContact} />
```

to

```jsx
<Detail key={activeContact.id} contact={activeContact} />
```

Pretty cool, since it only took this small change to achieve our desired UX.

Feel free to try out the Demo app by yourself. It's available as a [CodeSandbox example](https://codesandbox.io/s/polished-sun-9b9w4).

## Should You use this Technique?

Yes and no.

In general I noticed a lot of people struggle with the key attribute and why it is needed. From my understanding it was trade-off by the React team between usability and performance.

With that in mind I would try to avoid this technique and rather use useEffect in the Detail component to reset it or lift the state to a component containing the sidebar entry as well as the form.

So when when should you use? Well, sometimes there are deadlines or architectural issues that are hard to overcome and a quick win is desired. This technique is a tool in your tool belt and if it helps you to ship a better UX earlier, why not? But that doesn't mean you should design your application to leverage this technique heavily.

Of course there is also the concern that the implementation could change since it's not part of the documentation. Luckily in a [Twitter thread](https://twitter.com/sebmarkbage/status/1262937670444974081) initiated by Sebastian Markbåge (React team), he describes it as a valid use-case and Dan Abramov even [mentioned](https://twitter.com/dan_abramov/status/1262977196098048000) they will keep it in mind for the rewrite of the React docs.

One final note: Please add a code comment next to the `key` attribute explaining why it was needed and how it works. The next person not familiar with it will thank you. 🙂