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?
A key is the only thing React uses to identify DOM elements.
To understand the working of
key, let's understand React behavior withoutkeyfirst.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With