Ad

Why Doesn't ReactJS Autogenerate Keys For Dynamic Children?

- 1 answer

When coding ReactJS I have to supply keys for dynamic children. For example:

render() {
  const {options} = this.state
  const availableOptions = options.map(opt => {
    return (
      <option key={opt.id} value={opt.id}>{opt.displayValue}</option>}
    )
  }

  return (
    <select onChange={this._onOptionSelect}>
      {availableOptions}
    </select>
  )
}

I understand why they keys are there. But why do I have to give them? Couldn't react just assign a running number or UUIDv4 or something else?

Related doc: http://facebook.github.io/react/docs/multiple-components.html#dynamic-children

Ad

Answer

Tl;dr

You need to assign a unique key to dynamic elements that are associated with that element's data (maybe an id from a database field or something) because it stops unnecessary re-renders. This is the main draw of React and why it is noted for its performance.

Reason

You need to assign a unique key to dynamic children because this is how React's virtual DOM associates that element with a specific piece of data. I think an example would help illustrate.

Let's say you have a list of 1,000 dynamically generated items. You could just use the index parameter that is passed in from the map function to dynamically assign a key to those items. However, what if you wanted to change the order of those items - maybe sort them alphabetically? Because the key on those items is not tied to the specific piece of data and is instead just generated dynamically, the React virtual DOM has no way to keep track of those elements. That means it would have to re-render all 1,000 elements just to change the sorting. However, let's say each of those items had a unique id assigned to it that was populated from the database. The virtual DOM is smart enough to see that even though the order of the elements has changed, the data in the element itself is still the same. Therefore, it would re-render none of the elements, despite the fact that their order was changed.

If any of that is unclear, it makes total sense once you dissect how the virtual DOM really works. Essentially the virtual DOM is a copy of the actual DOM. React compares the two and only re-renders what has actually changed. This is where React gets its speed. So let's say you have a list of 3 dynamic <Item /> components and you are also generating their key dynamically.

<Item key="1">Banana</Item>
<Item key="2">Orange</Item>
<Item key="3">Apple</Item>

Now if you reorder those items alphabetically, their keys will also get reassigned dynamically.

<Item key="1">Apple</Item>
<Item key="2">Banana</Item>
<Item key="3">Orange</Item>

At this point React compares the contents of key 1 and sees if it has changed from the previous render of key 1. It has so it completely re-renders that element. Then it checks for key 2. Its contents have changed also, so that gets re-rendered. This continues for the whole list.

Now imagine that each item has a unique ID that is associated with it in the database and you assign this as the key.

<Item key="782364">Banana</Item>
<Item key="434533">Orange</Item>
<Item key="834535">Apple</Item>

Now we reorder that list alphabetically:

<Item key="834535">Apple</Item>
<Item key="782364">Banana</Item>
<Item key="434533">Orange</Item>

At this point React would check to see if the contents of the item with key 834535 are still the same. Well, the contents are still the same! So while that element gets a different order, it is not re-rendered. Then it checks for the element with key 782364 and finds that its contents are also the same. This also continues for the whole list.

While in a small list, you probably wouldn't notice the difference between a dynamically generated key vs. one that is tied directly to that element's data, for large lists the performance benefit is huge. And that really is the main draw of React - very smart re-rendering.

Ad
source: stackoverflow.com
Ad