Why doesn't ReactJS autogenerate keys for dynamic children?

ε祈祈猫儿з 提交于 2019-12-05 17:14:22

问题


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


回答1:


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.




回答2:


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!



来源:https://stackoverflow.com/questions/35338923/why-doesnt-reactjs-autogenerate-keys-for-dynamic-children

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!