Detailed explanation of the role of key in React

Detailed explanation of the role of key in React

To understand the role of key in React, we can start with the value of key. The value of key can be divided into three types: indefinite value, index value, and definite and unique value.

In the following code, the value of key is an indefinite value (Math.random())

Question: When the button is clicked, will the color of the span turn red?

import React, { useState } from 'react';

function App() {
  const [initMap, setInitMap] = useState([1,2,3,4]);
  const handleClick = () => {
    setInitMap([1,2,3,4])
    var spanEle = document.getElementsByTagName('span');
    Array.from(spanEle).map(it => it.style.color = 'red')
  }
  
  return (
    <div className="App" id="app">
      {
        initMap.map((it,index) => <div key={Math.random()}><span>color</span></div>)
      }
      <button onClick={() => handleClick()}></button>
    </div>
  );
}

export default App;

The answer is: No

This problem involves react rendering mechanism and diff algorithm

The official website has the following rules for diff:

  • When the element type changes, it will be destroyed and rebuilt
  • When the element type remains unchanged, compare the attributes
  • When the component element type remains unchanged, recursively determine the child nodes through props
  • Recursively compare child nodes. When the child node is a list, judge by key and props. If the keys are consistent, update them; if the keys are inconsistent, destroy and rebuild them.

Analyze the above problems:

When the button is clicked, setInitMap([1,2,3,4]) will cause rendering. When rendering, a new virtual DOM will be generated. However, the span element obtained at this time is the previous element (because setInitMap is executed asynchronously), so the new and old DOMs will be compared.

In the code initMap.map((it,index) => <div key={Math.random()}><span>color</span></div>)

The div here is a list. Compared with the fourth diff rule, react will determine whether to update the real DOM based on the key. key={Math.random()}, if the values ​​of the new and old doms are inconsistent, the div will be regenerated. We added a red style to the element before the update, so the recreated element will not have this style. The effect is as follows

The second case: the key value is the index value

The result of our analysis above is that due to the change of key, the div element will be regenerated when rendering. What if the key remains unchanged before and after render? For example, change key to index

Question: Will the color of the span change after the button is clicked in this code?

return (
    <div className="App" id="app">
      <Spin spinning={spin}></Spin>
      {
        initMap.map((it,index) => <div key={index}><span>color</span></div>)
      }
      <button onClick={() => handleClick()}></button>
    </div>
  );

Answer: Yes

Analysis: Because the index remains unchanged before and after render, the div will not be regenerated. Then compare the span element. The attributes of the span element change before and after render, so react will only apply new attributes to the span element, but they still point to the previous element.

The third case: the key value is determined and unique:

In this example, by setting the key to index, the color of the span changes, but when using keys, the React official website does not recommend using index.

Modify the above code

  const [initMap, setInitMap] = useState([1,2,3,4]);
  const handleClick = () => {
    setInitMap([3,2,1,4])
  }
  return (
    <div className="App" id="app">
      {
        initMap.map((it,index) => <div key={index}><input type="radio" />{it}</div>)
      }
      <button onClick={() => handleClick()}>Click</button>
    </div>
  );
}

When initializing, select the button with value 3

Click the button

The expected effect is that the button with a value of 3 is still selected, but now it becomes the button with a value of 1.

analyze:

  1. setState will cause render
  2. The index of the div does not change, so the div will not be regenerated, and the input is not controlled by state and props, so the state of the element does not change
  3. So the only thing that changes is it affected by state

If we want to achieve the desired effect, we need to set a unique and certain key

Test 1:

{
   initMap.map((it) => <div key={it}><input type="radio" />{it}</div>)
}

Select the third button during initialization

Click the button

This is the expected effect

Think about it, what effect will it have if you set the key to Math.random()? Will the button's state be preserved?

Before clicking:

After clicking:

The radio state is not preserved.

Through the above examples, we can probably understand the role of key in React. The following content is some expansion of React knowledge points

Extended content: The code at the beginning of the article also involves two other knowledge points of React, one is the React rendering conditions mentioned above, and the other is the operation of the real DOM;

Extension 1: React rendering conditions

import './App.css';
import React, { useState } from 'react';

function App() {
  const [initMap, setInitMap] = useState([1,2,3,4]);
  const [spin, setSpin] = useState(false);
  const handleClick = () => {
    setSpin(true); //Changed part var spanEle = document.getElementsByTagName('span');
    Array.from(spanEle).map(it => it.style.color = 'red')
    setSpin(false); //Change part}
  
  return (
    <div className="App" id="app">
      <Spin spinning={spin}></Spin>
      {
        initMap.map((it,index) => <div key={Math.random()}><span>{it}</span></div>)
      }
      <button onClick={() => handleClick()}></button>
    </div>
  );
}

export default App;

The test results are as follows before clicking:

After clicking:

In this code, the key of div still uses Math.random(), but the state of initMap has not changed, so it is not re-rendered. At this time, div will not be destroyed and rebuilt.

Extension 2: Is it possible to operate on the real DOM?

In React, the emergence of virtual DOM is to reduce the operation on the real DOM, because the real DOM element is a more complex object, and the operation requires a lot of calculation. In the code above, we directly manipulate the DOM node and change the style, which is not advisable. Since React renders pages based on changes in state and props, it is better to control page rendering through state.

The modified code is as follows:

function App() {
  const [initMap, setInitMap] = useState([1,2,3,4]);
  const [spin, setSpin] = useState(false);
  const [showColor, setShowColor] = useState(false);
  const handleClick = () => {
    setInitMap([3,2,1,4]);
    setShowColor(true);
  }
  
  return (
    <div className="App" id="app">
      <Spin spinning={spin}>
      {
        initMap.map((it,index) => <div key={Math.random()}><span className={showColor && 'span-color'}>color</span></div>)
      }
      </Spin>
      <button onClick={() => handleClick()}>Click</button>
    </div>
  );
}

At this time, span is a controlled component, and the rendering of the element can be controlled by the state of showColor

Before clicking:

After clicking:

After using state to control rendering, the amount of code will be reduced, and the results will meet expectations

Summarize

  1. When using keys, ensure that the keys are unique and deterministic. If the key value is Math.random(), it may cause the component to be rebuilt, making previous operations on the element invalid.
  2. When rendering a page, try not to manipulate the real DOM and use state to update the page

The above is a detailed explanation of the role of key in React. For more information about the role of React key, please pay attention to other related articles on 123WORDPRESS.COM!

You may also be interested in:
  • React Native reports "Cannot initialize a parameter of type''NSArray<id<RCTBridgeModule>>" error (solution)
  • Summary of react basics
  • Detailed explanation of data transmission between React parent components and child components
  • React entry-level detailed notes

<<:  How to configure two-way certificate verification on nginx proxy server

>>:  MySQL 5.7.18 master-slave replication setup (one master and one slave) tutorial detailed explanation

Recommend

How to use Navicat to export and import mysql database

MySql is a data source we use frequently. It is v...

The whole process of installing mysql5.7.22 under ARM64 architecture

MySQL download address: https://obs.cn-north-4.my...

The neglected special effects of META tags (page transition effects)

Using js in web design can achieve many page effec...

How to use Linux tr command

01. Command Overview The tr command can replace, ...

Docker container custom hosts network access operation

Adding the extra_hosts keyword in docker-compose....

InnoDB type MySql restore table structure and data

Prerequisite: Save the .frm and .ibd files that n...

js implements the classic minesweeper game

This article example shares the specific code of ...

MySQL 5.7.12 installation and configuration tutorial under Mac OS 10.11

How to install and configure MySQL on Mac OS 10.1...

10 very good CSS skills collection and sharing

Here, clever use of CSS techniques allows you to g...

Discussion on the way to open website hyperlinks

A new window opens. Advantages: When the user cli...

How to use display:olck/none to create a menu bar

The effect of completing a menu bar through displ...

Explanation of the usage scenarios of sql and various nosql databases

SQL is the main trunk. Why do I understand it thi...

Query the data of the day before the current time interval in MySQL

1. Background In actual projects, we will encount...