preface

When developing React or Vue, we have a list traversal operation, which usually binds a key value. What is the use of this key? Why is it best not to use index for key when iterating through a list?

Today we’ll take a look at the React virtual DOM keys and indexes.

The role of keys in the virtual DOM

To put it simply: The key is the identity of the virtual DOM object and plays an extremely important role in updating the display.

React generates a new virtual DOM based on the new data. Then React makes a diff comparison between the new virtual DOM and the old virtual DOM. The comparison rules are as follows:

  • A. The same key as the new virtual DOM is found in the old virtual DOM:
    • (1). If the content in the virtual DOM remains unchanged, use the previous real DOM directly
    • (2). If the content in the virtual DOM changes, a new real DOM is generated and the previous real DOM in the page is replaced
  • B. The old virtual DOM does not have the same key as the new virtual DOM
    • Create a new real DOM from the data and render it to the page

The sample code

For convenience, I’ll put index as the key and id as the key together. Let’s see what happens:

import React, { Component } from "react";

export default class example17 extends Component {
  state = {
    persons: [{id: 1.name: "Zhang".age: 18 },
      { id: 2.name: "Xiao li".age: 19},]}; add =() = > {
    const { persons } = this.state;
    const p = { id: persons.length + 1.name: "Wang".age: 20 };
    this.setState({ persons: [p, ...persons] });
  };

  render() {
    return (
      <div>
        <h2>Display personnel information</h2>
        <button onClick={this.add}>Add a little wang</button>
        <h3>Use index as the key</h3>
        <ul>
          {this.state.persons.map((personObj, index) => {
            return (
              <li key={index}>
                {personObj.name}---{personObj.age}
                <input type="text" />
              </li>
            );
          })}
        </ul>
        <hr />
        <hr />
        <h3>Use id (the unique identification of the data) as the key</h3>
        <ul>
          {this.state.persons.map((personObj) => {
            return (
              <li key={personObj.id}>
                {personObj.name}---{personObj.age}
                <input type="text" />
              </li>
            );
          })}
        </ul>
      </div>); }}Copy the code

Effect:

Slow motion playback —- Use index as the key

In the above renderings, zhou Xingxing was entered into the input box for Xiao Li -19, but after adding Xiao Wang, Zhou Xingxing ran to Xiao Zhang -18

Why is that? Let’s analyze a wave:

Initial data:

{id:1.name:'zhang'.age:18}
{id:2.name:'xiao li'.age:19}
Copy the code

The initial virtual DOM:

<li key={0} - > xiao zhang18<input type="text"/></li>
<li key={1}>Xiao li - 19<input type="text"/></li>
Copy the code

Updated data:

{id:3.name:'wang'.age:20},
{id:1.name:'zhang'.age:18},
{id:2.name:'xiao li'.age:19},
Copy the code

Virtual DOM after data update:

<li key={0} - > wang20<input type="text"/></li>
<li key={1}>Zhang - 18<input type="text"/></li>
<li key={2}>Xiao li - 19<input type="text"/></li>
Copy the code

When first rendered, the key property of the subcomponent list is assigned to the array index. If a new component is inserted at the end of the subcomponent list, the index of the previous component does not change. However, after reordering the data, the index of the array index still steadily increases from 0. React considers that the component has not changed, so the input box under the array index is still under the array index.

Slow motion playback —- Use the unique ID as the key

So why don’t we see that with id unique?

Here’s another wave:

Initial data:

{id:1.name:'zhang'.age:18}
{id:2.name:'xiao li'.age:19}
Copy the code

The initial virtual DOM:

<li key={1} - > xiao zhang18<input type="text"/></li>
<li key={2}>Xiao li - 19<input type="text"/></li>
Copy the code

Updated data:

{id:3.name:'wang'.age:20},
{id:1.name:'zhang'.age:18},
{id:2.name:'xiao li'.age:19},
Copy the code

Virtual DOM after data update:

<li key={3} - > wang20<input type="text"/></li>
<li key={1}>Zhang - 18<input type="text"/></li>
<li key={2}>Xiao li - 19<input type="text"/></li>
Copy the code

The reason: It’s very simple. The key has changed. The React Diff algorithm says the component has changed and I’m going to move the element from left to right. There is a serious problem here because we are adding an element to the front, which is bad for multi-data situations.

conclusion

We can see the problems that can arise when using index as the key:

  1. If the data is added or deleted in reverse order, the sequence is broken:
    • Produces unnecessary real DOM updates to the ==> interface, which is fine, but inefficient.
  2. If the structure also contains the DOM of the input class:
    • Error DOM update ==> interface problem.
  3. Attention! It is ok to use index as key if there is no order breaking operation such as adding or deleting data in reverse order and only used for rendering list for display.

So how do we choose the value of the Key?

React recommends that the value of the key attribute be a unique identifier of the string type. Usually, this identifier comes from the data returned by the API to the front end. The data returned by the back end usually contains a field such as ID, which is globally unique and stably stored in the persistence layer. Index can also be used if it is for presentation only

expand

  • Why do React list cycle need key | interview questions
  • React, Vue2, Vue3 Diff algorithm

Extra knowledge: Vue and React Diff algorithm comparison

Similarities:

  • The DIff algorithms of Vue and React do not make cross-level comparisons, but only peer comparisons.

Difference:

  • When Vue diff, it calls the patch patching function and patches the real DOM while comparing
  • 2.Vue compares nodes. When nodes have the same element type but different classnames, they are considered to be of different types and deleted
  • The list comparison of Vue adopts the way from both ends to the middle. There are two Pointers at both ends of the old set and the new set for comparison in pairs. If there is a match, the old set will be adjusted according to the new set.
  • React compares elements from left to right using index and lastIndex. If index < lastIndex, the element is moved, while deleting and adding elements are adjusted according to the rules respectively.
  • When a set moves the last node to the front, React moves the previous nodes back, while Vue only moves the last node to the front. In this case, Vue’s DIff performance is higher than React’s