[Перевод] Ref-атрибуты и DOM в React

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


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


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


В типовом потоке данных React, свойства (props) — это единственный способ, с помощью которого родители взаимодействуют со своими потомками. Для модификации потомка, вам необходимо заново отобразить (произвести ререндеринг) его с новыми свойствами. Однако, в некоторых случаях, вам понадобится модифицировать потомка непосредственно, вне основного потока. Изменение потомка возможно в случаях если он является экземпляром компонента 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 (
      
{ this.textInput = input; }} />
); } }

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 (
      
{ this.textInput = input; }} />
); } } class AutoFocusTextInput extends React.Component { componentDidMount() { this.textInput.focus(); } render() { return ( { this.textInput = input; }} /> ); } }

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


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

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

  return (
    
{ textInput = input; }} />
); }

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


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


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


  • PropTypes — проверка типов в React.
  • JSX — подробности.

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

Комментарии (5)

  • 14 января 2017 в 03:19 (комментарий был изменён)

    +1

    Как альтернатива — можно использовать строковое название и тогда не придется каждый вызов создавать анонимную функцию, не знаю, почему в статье нету этого примера.
    class Hello extends React.Component {
      constructor() {
        this.focus = this.focus.bind(this);
      }
    
      handleClick() {
        this.refs.myTextInput.focus();
      }
    
      render() {
        return (
          
    ); } }

    edit: таки описано:

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

    не хватает аргументов, почему рекомендуют.

    • 14 января 2017 в 03:22 (комментарий был изменён)

      0

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

      0

      Не надо давать уникальные имена универсальным шаблонным элементам, можно использовать универсальные функции. Представьте, что у вас 2 inputa и 2 кнопки. И там и там одинаковый функционал.
      • 14 января 2017 в 04:37

        0

        Звучит как место для вывода кода в отдельный компонент. Но я не могу понять, что именно вы предлагаете.
      • 14 января 2017 в 07:31

        0

        Как различать какие элементы демонтируются?

© Habrahabr.ru