- PVSM.RU - https://www.pvsm.ru -

Ref-атрибуты и DOM в React

React. Продвинутые руководства. Часть Третья

Продолжение серии переводов раздела "Продвинутые руководства" (Advanced Guides) официальной документации библиотеки React.js.

Ref-атрибуты и DOM в React

В типовом потоке данных React, свойства (props) [1] — это единственный способ, с помощью которого родители взаимодействуют со своими потомками. Для модификации потомка, вам необходимо заново отобразить (произвести ререндеринг) его с новыми свойствами. Однако, в некоторых случаях, вам понадобится модифицировать потомка непосредственно, вне основного потока. Изменение потомка возможно в случаях если он является экземпляром компонента React или элементом DOM. Для обоих этих случаев React имеет особый способ изменения.

Атрибут обратного вызова ref

React поддерживает специальный атрибут, который может быть присвоен любому компоненту. Атрибут ref принимает функцию обратного вызова, и вызывает ее после того, как компонент монтируется в DOM или удаляется из него.

Когда атрибут ref используется в элементе HTML, функция обратного вызова принимает базовый элемент DOM в качестве аргумента. Например, следующий код использует функцию обратного вызова, указанную в ref, для сохранения ссылки на узел DOM:

class CustomTextInput extends React.Component {
  constructor(props) {
    super(props);
    this.focus = this.focus.bind(this);
  }

  focus() {
    // Установка фокуса на поле текстового ввода (input) с явным использованием исходного API DOM
    this.textInput.focus();
  }

  render() {
    // Использование обратного вызова `ref` для сохранения ссылки на поле текстового ввода (input)
    // как элемента DOM в this.textInput.
    return (
      <div>
        <input
          type="text"
          ref={(input) => { this.textInput = input; }} />
        <input
          type="button"
          value="Focus the text input"
          onClick={this.focus}
        />
      </div>
    );
  }
}

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

Использование обратного вызова ref для установки свойства в классе — это общепринятый шаблон для доступа к элементам DOM. Если в настоящий момент для этой задачи вы используете this.refs.myRefName, мы рекомендуем перейти к использованию описанного нами шаблона.

Когда атрибут ref используется в кастомном компоненте React, функция обратного вызова принимает смонтированный экземпляр компонента в качестве аргумента. Например, если мы захотели обернуть input из предыдущего примера в компонент CustomTextInput для симуляции клика сразу после монтирования:

class CustomTextInput extends React.Component {
  constructor(props) {
    super(props);
    this.focus = this.focus.bind(this);
  }

  focus() {
    // Установка фокуса на поле текстового ввода (input) с явным использованием исходного API DOM
    this.textInput.focus();
  }

  render() {
    // Использование обратного вызова `ref` для сохранения ссылки на поле текстового ввода (input)
    // как элемента DOM в this.textInput.
    return (
      <div>
        <input
          type="text"
          ref={(input) => { this.textInput = input; }} />
        <input
          type="button"
          value="Focus the text input"
          onClick={this.focus}
        />
      </div>
    );
  }
}

class AutoFocusTextInput extends React.Component {
  componentDidMount() {
    this.textInput.focus();
  }

  render() {
    return (
      <CustomTextInput
        ref={(input) => { this.textInput = input; }} />
    );
  }
}

Нельзя использовать атрибут ref с компонентом, построенным на функции (stateless компонент), т.к. функция не имеет экземпляров. Однако, вы можете использовать атрибут ref внутри такого компонента:

function CustomTextInput(props) {
  // textInput задекларирован здесь, т.к. обратный вызов ref ссылается на него
  let textInput = null;

  function handleClick() {
    textInput.focus();
  }

  return (
    <div>
      <input
        type="text"
        ref={(input) => { textInput = input; }} />
      <input
        type="button"
        value="Focus the text input"
        onClick={handleClick}
      />
    </div>
  );  
}

Не злоупотребляйте обратными вызовами ref

Вашей первой мыслью может быть — что использование ref "превратит мечту в реальность" в вашем приложении. Если это так, то остановитесь и критически подумайте — верно ли расположены состояния в вашей иерархии компонентов. Часто возникает такая ситуация, что перерасположение состояния выше в иерархии компонентов, чем оно находится в настоящий момент, решает проблему. Смотрите руководство Подъем Состояния выше [2] как пример этого.

Предыдущие части:

Первоисточник: React — Advanced Guides — Refs and the DOM [5]

Автор: vtikunov

Источник [6]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/javascript/233169

Ссылки в тексте:

[1] свойства (props): https://facebook.github.io/react/docs/components-and-props.html

[2] Подъем Состояния выше: https://facebook.github.io/react/docs/lifting-state-up.html

[3] PropTypes — проверка типов в React.: https://habrahabr.ru/post/319358/

[4] JSX — подробности.: https://habrahabr.ru/post/319270/

[5] React — Advanced Guides — Refs and the DOM: https://facebook.github.io/react/docs/refs-and-the-dom.html

[6] Источник: https://habrahabr.ru/post/319510/?utm_source=habrahabr&utm_medium=rss&utm_campaign=best