Why use itkey

Motivation

When you use React, at a single point in time you can think of the render() function as creating a tree of React elements. On the next state or props update, that render() function will return a different tree of React elements. React then needs to figure out how to efficiently update the UI to match the most recent tree.

When you use React, you can treat the Render () function as creating a React element tree at a single point in time. On the next state or item update, the Render () function returns a different React element tree. Then React needs to figure out how to efficiently update the UI to match the latest tree.

Two problems of algorithm complexity are involved here. In a word, they are:

  • Two elements of different types produce different trees
  • Developers can passkeyTo indicate which child elements can be stable across different renders

How does Key work?

The React key property is a special property that exists not for developers (for example, you can’t get the key props of a component after setting the key for it), but for React itself.

React uses a key to identify components, which is a kind of identification identifier, just like our ID cards identify a person. React considers the same key to be the same component. In this way, components corresponding to the same key will not be created later.

this.state = {
 users: [{id:1,name: 'Joe'}, {id:2, name: 'bill'}, {id: 2, name: "Fifty"}],... // omit} render()return(< div > < h3 > user list < / h3 > {this. State. Users. The map (u = > < div key = {u.i d} > {} u.i d: {u.n ame} < / div >)} < / div >));Copy the code

After the above code is mounted in DOM rendering, there are only two users in the user list: Jason and Jason. The king does not show processing, mainly because React thinks that Jason and Jason are the same component according to the key, so the first one will be rendered and the subsequent ones will be discarded.

The value of key must be unique and stable

React uses the key to determine whether to destroy and recreate the component or to update it.

  • React updates only the component properties if the key is the same. No change, no update.

  • React destroys the component (stateful component constructor and componentWillUnmount) and re-creates the component (stateful component constructor and componentWillUnmount).

That’s not all (I’ll say a few more words). The most common use of the key attribute in project development is for dynamically created child components, each of which needs to have a unique key attribute value.

indexThe use of

When I use a key to identify the child components of a list array, I usually do this:

{this.state.data.map((v, IDx) => <Item key={idx} v={v} />)} // index as key"0">a <input type="text"/></li>
    <li key="1">b <input type="text"/></li>
    <li key="2">c <input type="text"/></li>
</ul>
Copy the code

But…

When dynamic changes to the array are involved, such as adding, deleting, or reordering elements, the index key will display the wrong data.

{this. State. Data. The map (= (v, independence idx) > < Item key = v = {n} {independence idx} / >)} / / at the beginning: ['a'.'b'.'c']=>
<ul>
    <li key="0">a <input type="text"/></li>
    <li key="1">b <input type="text"/></li>
    <li key="2">c <input type="text"/></li> </ul>'c'.'b'.'a'] =>
<ul>
    <li key="0">c <input type="text"/></li>
    <li key="1">b <input type="text"/></li>
    <li key="2">a <input type="text"/></li>
</ul>

Copy the code

In the above example, after the array is reordered, the instances corresponding to the key are not destroyed, but updated. Insert key=0; insert key=0;

  • The component is rerendered to get a new virtual DOM.

  • React considers a component to be the same, so only the component can be updated.

  • And then compare their children, found that the content of the text content is different (from a – > c), and input component did not change, then trigger a component componentWillReceiveProps method, so as to update their text content;

  • Because components of children in the input component did not change, its components and father is no connection between the incoming President of props, so the input component does not update (namely the componentWillReceiveProps methods will not be executed), causes the user input values will not change.

This is the problem with index as a key. Index as a key is an anti-pattern and should not be used lightly. (If the contents of an array are purely presentable and do not involve dynamic changes to the array, it is recommended.)

There are two demos on the official website: Demo1 and Demo2.

indexAn alternative

After all, the problem with using index is that the index is the same and the key is the same. Go back to 👆 : If the key is the same, react only updates the corresponding attribute of the component. No change, no update.

At this point, if you make sure that the key is different each time, wouldn’t the problem be solved?

As a result…

key={index +  Math.random()}
Copy the code

A magical line of code is created.

Can it solve the problem? Can!!!! Is it optimal? It isn’t.

Don’t pass something like math.random () to keys.

Keys should be stable, predictable, and unique. Unstable keys, such as the key math.random () generated by them, cause many component instances and DOM nodes to be recreated unnecessarily, which can lead to performance degradation and lost state in child components.

So, in cases where random cannot be used to generate keys randomly, we can use a global localCounter variable to add a stable unique key value as shown below.

var localCounter = 1;
this.data.forEach(el=>{
    el.id = localCounter++; }); // When adding an element to an array dynamically,function createUser(user) {
    return {
        ...user,
        id: localCounter++
    }
}
Copy the code

So, my final solution was to define a variable globally: let ONE = 1; And then use key = {ONE++} in the component. In this way, the key changes every time when setSete() is performed, and the unstable nature of the key is avoided to a certain extent. Problem solved, call it a day.

To supplement the problem scenario:

The problem was that it was the inner component properties that needed to be changed, while the key was set above the outer child components. React uses index as the key. The index is the same for the outer layer child. React finds key = index and finds the key unchanged. React updates only the component properties if the key is the same. No change, no update. There are no properties that change on the outer child component; the properties that change are on the inner component. React terminates when it finds the outer child component. The inner layer subcomponent is still not rendered.

Reference:

React Key

React Chinese document key

React Chinese document key