admin管理员组

文章数量:1392050

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: .html#dynamic-children

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-ponents.html#dynamic-children

Share Improve this question asked Feb 11, 2016 at 12:06 elnygrenelnygren 5,3554 gold badges22 silver badges33 bronze badges
Add a ment  | 

2 Answers 2

Reset to default 9

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 pares 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 /> ponents 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 pares the contents of key 1 and sees if it has changed from the previous render of key 1. It has so it pletely 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.

Why doesn't ReactJS autogenerate keys for dynamic children?

It does, because it needs something to identifiy the elements in the virtual dom tree. If you inspect the generated html for some dynamic children with the key prop omitted you'll see:

Where key ∈ {0,1,2,3}

But that is unspecified behaviour and you should not rely on that. The warning is there because:

  • React does not and does want to make any assumptions about your application. It is the responsibilty of the developer to supply a suitable key, so that all the react specific optimizations (e.g. reuse of dom nodes) can be applied.
  • They (Facebook) can change the unspecified default behaviour at any time and thus break any code that relies on that.

It cannot be repeated often enough: Don't rely on the default behaviour!

本文标签: javascriptWhy doesn39t ReactJS autogenerate keys for dynamic childrenStack Overflow