Реакт по своей природе изолирует нас от прямой работы с DOM на 100%. Но нередко при интеграции сторонних не-Реакт компонентов возникает задача по прямому доступу к DOM. Также подобный механизм нужен для выделения текста, фокусов и проигрывания медиа.

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

Рассмотрим задачу по фокусировке на поле ввода:

See the Pen js_react_refs_focus by Hexlet (@hexlet) on CodePen.

ref — это свойство компонента, значением которого должен быть объект, созданный в конструкторе через функцию React.createRef(). Этот объект, в отличии от остальных данных, которые хранятся в props или state, хранится как обычное свойство объекта. Имя свойства можно выбрать произвольно. Свойство current этого объекта дает доступ к элементу DOM, именно его можно использовать в componentDidMount или componentDidUpdate.

Ниже приведен пример создания компонента обертки над популярным JQuery плагином Chosen.

See the Pen js_react_refs_dom by Hexlet (@hexlet) on CodePen.

ref так же может использоваться и на самописных компонентах, реализованных как классы.

Функциональные компоненты не поддерживают аттрибут ref, так как у них нет инстанса. Если вам нужна работа с DOM, то придется конвертировать такой компонент в класс.

Использование в реальном мире

С Реактом удобно и легко работать до тех пор, пока мы остаемся в рамках самого Реакта, но большая часть существующих js библиотек взаимодействует с домом напрямую, что фактически невилирует преимущества реакта при их использовании напрямую. Например:

// https://github.com/kylefox/jquery-modal
$('#login-form').modal();

Включение в проект таких библиотек неизбежно приведет к активному использованию lifecycle методов и сделает код сложным. По этой причине, принято создавать так называемые врапперы, компоненты-обертки, которые скрывают внутри себя все взаимодействие в домом и наружу выставляют стандартный интерфейс реакта, а именно пропсы. Одной из таких задач является ресайз контейнера. Один из вариантов решения, компонент react-resizable. Посмотрите на работу этого компонента:

const Resizable = require('react-resizable').Resizable; // or,
const ResizableBox = require('react-resizable').ResizableBox;

// ES6
import { ResizableBox } from 'react-resizable';

// ...
render() {
  return (
    <ResizableBox width={200} height={200} minConstraints={[100, 100]} maxConstraints={[300, 300]}>
      <span>Contents</span>
    </ResizableBox>
  );
}

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