Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How React Can Change Components With Key Attribute?

My Root Component

import React, {Component} from 'react';
import Task from "./components/task";

class App extends Component {

    state = {
        keys: [0, 1]
    }

    changeKeysHandler = () => {
        const { keys } = this.state;
        const newKeys = keys.slice().reverse();
        this.setState({
            keys: newKeys
        })
    }

    render() {
        return (
            <div>
                <Task key={this.state.keys[0]}/>
                <Task key={this.state.keys[1]}/>
                <button onClick={this.changeKeysHandler}>Reverse</button>
            </div>
        )
    }
}

export default App;

My Task Component

import React, {useState} from "react";

export default function Task() {
    const [ value, setValue ] = useState("Tofiq")
    return(
        <div>
            <input
                type="text"
                value={value}
                onChange={(event) => { setValue(event.target.value) }}
            />
        </div>
    )
}

When I change keys React Components change orders. But I don't understand what is happening under the hood. How React key attributes related with components. Can you explain the implantation of this to me?

like image 235
Murad Sofiyev Avatar asked Oct 29 '25 13:10

Murad Sofiyev


1 Answers

A key is the only thing React uses to identify DOM elements.

To understand the working of key, let's understand React behavior without key first.

Let's say we have a list

<ul>
  <li>first</li>
  <li>second</li>
</ul>

By default, when recursing on the children of a DOM node, React just iterates over both lists of children at the same time and generates a mutation whenever there’s a difference.

For example, when adding an element at the end of the children, converting between these two trees works well:

<ul>
  <li>first</li>
  <li>second</li>
  <li>third</li>
</ul>

React will match the two <li>first</li> trees, match the two <li>second</li> trees, and then insert the <li>third</li> tree.

Insert an element at the beginning has worse performance. For example, converting between these two trees works poorly, and React will mutate every child instead of realizing it can keep the <li>Duke</li> and <li>Villanova</li> subtrees intact. This inefficiency can be a problem.

Keys

In order to solve this issue, React supports a key attribute. When children have keys, React uses the key to match children in the original tree with children in the subsequent tree.

For example, adding a key to our inefficient example above can make the tree conversion efficient:

<ul>
  <li key="2015">Duke</li>
  <li key="2016">Villanova</li>
</ul>

<ul>
  <li key="2014">Connecticut</li>
  <li key="2015">Duke</li>
  <li key="2016">Villanova</li>
</ul>

Now React knows that the element with key '2014' is the new one, and the elements with the keys '2015' and '2016' have just moved.

Now let's talk about your problem

React's key prop gives you the ability to control component instances. Each time React renders your components, it's calling your functions to retrieve the new React elements that it uses to update the DOM. If you return the same element types, it keeps those components/DOM nodes around, even if all* the props changed.

In your case component instances are updated and reused based on their key. On changing the key of the list, the component state for things like uncontrolled inputs can get mixed up and updated in unexpected ways.

like image 125
harish kumar Avatar answered Oct 31 '25 12:10

harish kumar



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!