Как работают ключи React и интересные вещи, которые вы можете делать с ними

1656615615 kak rabotayut klyuchi react i interesnye veshhi kotorye vy mozhete

Кристоф Мишель

j1gj-Ft2oP575ZRnXgRUL0RGOFgEk7sYo4Dr

React использует key атрибут при согласовании, чтобы решить, какие элементы можно повторно использовать для последующей визуализации. Они важны для динамических списков. React сравнит ключи нового элемента с предыдущими ключами и 1) смонтирует компоненты с новым ключом 2) размонтирует компоненты, ключи которых больше не используются.

Многие разработчики React слышали общие советы, которыми не стоит пользоваться index как ключ. Но что именно может пойти не столько при использовании keyв плохом состоянии? Что мы еще можем делать, когда играем с ключами?

Для лучшего понимания рассмотрим пример воспроизведения списка inputс. При нажатии кнопки мы вставим новый элемент с текстом Front на фронт из списка.

import React from "react";import { render } from "react-dom";class Item extends React.PureComponent {  state = {    text: this.props.text  };  onChange = event => {    this.setState({      text: event.target.value    });  };  componentDidMount() {    console.log("Mounted ", this.props.text);  }  componentWillUnmount() {    console.log("Unmounting ", this.props.text);  }  render() {    console.log("rerendering ", this.props.text);    const { text } = this.state;    return (      <li>        <input value={text} onChange={this.onChange} />      </li>    );  }}class App extends React.Component {  state = {    items: [      {        text: "First",        id: 1      },      {        text: "Second",        id: 2      }    ]  };  addItem = () => {    const items = [{ text: "Front", id: Date.now() }, ...this.state.items];    this.setState({ items });  };  render() {    return (      <div>        <ul>          {this.state.items.map((item, index) => (            <Item {...item} key={index} />          ))}        </ul>        <button onClick={this.addItem}>Add Item</button>      </div>    );  }}render(<App />, document.getElementById("root"));

Если вы используете index как ключ, происходит следующее:

CodeSandbox
CodeSandbox – это онлайн-редактор, разработанный для веб-приложений.codesandbox.io

AG7Wjs11dx4F6d7F4lkLf6zFs622uFqOTLlt

А если другой Item с текстом Second вместо Front вставлено на задней из списка? Вот что происходит:

  1. Item is an uncontrolled component: текст, в который записывает пользователь input поле сохраняется как state
  2. Новый элемент данных { text: "Front" } вставляется в начало данных списка.
  3. Список повторно воспроизводится с помощью индекс значение как key. Поэтому предыдущие компоненты повторно используются для первых двух элементы данных и получают правильный реквизит Front и Firstно состояние не обновляется в Item. Вот почему первые два экземпляра компонентов хранят тот же текст.
  4. Создано новый экземпляр компонента для key: 2 поскольку предыдущий ключ не найден. Он наполнен props последних элемент данных списка какой есть Second.
5wLO4ksFCdVvKeDvMDshS8FrUWoiSFOvxI6l

Еще одним интересным моментом является render происходящие звонки. Пункт а PureComponentпоэтому он обновляется только тогда, когда text изменения опоры (или состояния):

rerendering  Frontrerendering  Firstrerendering  SecondMounted  Second

все компоненты повторно воспроизводятся. Это происходит потому, что элемент с key: 0 повторно используется для первого элемента данных и получает его propsно первый элемент данных теперь новый Front объект, вызывающий а render. То же происходит с другими компонентами, поскольку старые элементы данных теперь все смещены на одно место.

Итак, что поправить? Исправить это легко: мы предоставляем каждому элементу данных списка уникальность id однажды при создании (не на каждом рендере!). Все экземпляры компонентов согласуются с соответствующим элементом данных. Они получают то же самое props по-прежнему, и это избегает другого render.

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

Если мы перепишем Item как контролируемый компонент, перемещая состояние из него, ошибка исчезает.

Почему? Опять же, потому что ошибка была повторное использование компонента другого элемента данных. Поэтому внутреннее состояние еще отображает состояние предыдущего элемента данныхно реквизит другого. Сделав компонент контролируемым, полностью удалив его состояние, мы больше не имеем этого несоответствия. (Но все еще существует проблема с ненужными повторными визуализации.)

Злоупотребление ключами для исправления сломанных компонентов сторонних разработчиков

Реагируйте только на нужды keys при совпадении нескольких элементов, поэтому устанавливать ключ для одного ребенка не нужно. Но все равно может быть полезно установить ключ для одного дочернего компонента.

Если вы измените ключ, React выбросит весь компонент (размонтирует его) и смонтирует новый экземпляр компонента на его место. Почему это может оказаться полезным?

Мы снова возвращаемся к неконтролируемые компоненты. Иногда вы используете сторонний компонент и не можете изменить его код, чтобы сделать его контролируемым. Если компонент имеет некоторое внутреннее состояние и он реализован плохо (например, состояние только производное один раз в конструкторе, но getDerivedStateFromProps / componentWillReceiveProps не реализуется до отражают повторяемость props изменения его внутреннего состояния), стандартная панель инструментов React здесь не поможет. Нету forceRemount.

Однако мы можем просто установить новый key на этом компоненте, чтобы добиться желаемого поведения полной инициализации нового компонента. Старый компонент будет демонтирован, а новый будет смонтирован вместе с новым props инициализация state.

TL; DR:

Использование index как ключ может:

  1. привести к ненужным повторным визуализации
  2. вводить ошибки, когда есть элементы списка неконтролируемые компоненты но все равно пользуйся props

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

Первоначально опубликовано на cmichel.io

ZpVxptp2LfM-Ia7ksRx3CnJ-dCuVnoxUBGGN

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *