Как React может изменить компоненты с ключевым атрибутом? - PullRequest
1 голос
/ 20 июня 2020

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>
    )
}

Когда я меняю ключи, компоненты React меняют порядок. Но я не понимаю, что происходит под капотом. Как ключевые атрибуты React связаны с компонентами. Не могли бы вы объяснить мне имплантацию этого?

1 Ответ

0 голосов
/ 20 июня 2020

A key - единственное, что React использует для идентификации DOM элементов.

Чтобы понять работу key, давайте сначала разберемся с поведением React без key.

Допустим, у нас есть список

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

По умолчанию при рекурсии по дочерним элементам узла DOM React просто выполняет итерацию по обоим спискам дочерних элементов одновременно и генерирует мутацию всякий раз, когда есть разница.

Например, при добавлении элемента в конце дочерних элементов преобразование между этими двумя деревьями работает хорошо:

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

React будет соответствовать два дерева <li>first</li>, сопоставьте два дерева <li>second</li>, а затем вставьте дерево <li>third</li>.

Вставка элемента в beginning имеет худшую производительность. Например, преобразование между этими двумя деревьями работает плохо, и React мутирует каждого дочернего элемента вместо того, чтобы понимать, что он может сохранить поддеревья <li>Duke</li> и <li>Villanova</li> нетронутыми. Эта неэффективность может быть проблемой.

Ключи

Чтобы решить эту проблему, React поддерживает атрибут key. Когда дочерние элементы имеют keys, React использует key для сопоставления дочерних элементов в исходном дереве с дочерними элементами в последующем дереве.

Например, добавление key к нашему неэффективному примеру выше может сделать дерево эффективность преобразования:

<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>

Теперь React знает, что элемент с ключом '2014' является новым, а элементы с ключами '2015' и '2016' только что перемещены.

Теперь давайте поговорим о вашей проблеме

Свойство key в React дает вам возможность управлять экземплярами компонентов. Каждый раз, когда React визуализирует ваши компоненты, он вызывает ваши функции для получения новых элементов React, которые он использует для обновления файла DOM. Если вы возвращаете те же типы элементов, он сохраняет эти components/DOM узлы, даже если все * свойства изменились.

В вашем случае экземпляры компонентов обновляются и повторно используются на основе их ключа. При изменении key списка состояние компонента для таких вещей, как неконтролируемые вводы, может быть перепутано и обновлено неожиданными способами.

...