Освойте использование рефери, чтобы вывести свою игру на React на новый уровень

React - одна из самых популярных библиотек для создания веб-приложений в 2020 году. Когда мы работаем с React, мы перекладываем на него ответственность за рендеринг и обновление DOM.

React поощряет нас писать наши приложения и наши компоненты декларативным образом. Это отговаривает нас от прямого доступа к DOM и обязательного изменения DOM. Однако иногда нам нужно выполнить задачи, которые просто невозможно выполнить с помощью декларативной модели React. В этих случаях мы используем refs.

Однако команда React целыми днями работает над (отличной) библиотекой для создания пользовательских интерфейсов. Те из нас, кто работает в реальном мире, работая над приложениями, ориентированными на клиентов, знают, что иногда нам приходится отказываться от декларативной модели, чтобы выполнить свою работу.

В чем разница между createRef и useRef?

До того, как были выпущены перехватчики React, мы использовали для создания ссылок createRef API. С момента выпуска хуков React мы можем рассчитывать на React.useRef.

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

Это означает, что мы можем использовать useRef для сохранения значений в течение срока службы наших компонентов и обновления этих значений, не вызывая повторной визуализации. Позже мы воспользуемся этой функцией для создания ловушки usePrevious.

Когда мы должны использовать ссылки в React?

1. Вам необходимо получить прямой доступ к элементу DOM.

Нужно сфокусировать элемент? Нужно воспроизвести или приостановить видео? Это некоторые из многих случаев, когда вам нужно использовать исх.

В приведенном ниже коде создается компонент React с именем VideoPlayer. Пользователи могут нажимать определенные кнопки, чтобы воспроизвести или приостановить воспроизведение видео.

const VideoPlayer = ({ src, ...props }) => {
  const ref = React.useRef();
const handlePlay = () => {
    ref.current.pause();
  };
  const handlePause = () => {
    ref.current.pause();
  };
  return (
    <div>
      <button onClick={handlePlay}>Play</button>
      <button onClick={handlePause}>Pause</button>
      <video src={src} ref={ref} {...props} />
    </div>
  );
};

2. Обнаружение внешних кликов

Вы когда-нибудь писали модальный или раскрывающийся компонент и пытались выяснить, как скрыть свой компонент, когда пользователь щелкает мышью? Звучит как сложная проблема, но ее довольно легко решить с помощью ссылок.

Пользовательский хук ниже принимает ссылку и обратный вызов и вызывает обратный вызов, когда пользователь щелкает за пределами вашего компонента.

const useClickOutside = (ref, callback) => {
  React.useEffect(() => {
    function handleClickOutside(event) {
      if (ref.current && !ref.current.contains(event.target)) {
        callback();
      }
    }
document.addEventListener("mousedown", handleClickOutside);
    return () => {
      document.removeEventListener("mousedown", handleClickOutside);
    };
  }, [ref]);
};

3. Сохранение изменяемого состояния

Использование ссылок для обработки изменяемого состояния может быть полезно, если вы хотите предотвратить повторный рендеринг ваших компонентов. Один из распространенных вариантов использования этого - реализация ловушки usePrevious. С помощью этого хука вы можете отслеживать предыдущее значение одной из ваших переменных состояния.

const usePrevious = (value) => {
  const ref = React.useRef();
    useEffect(() => {
    ref.current = value;
  }, [value]);
  
  return ref.current;
}

4. Интеграция со сторонними библиотеками.

К сожалению, нам не всегда удается работать с новым, блестящим программным обеспечением. Иногда вы можете застрять в работе над устаревшим программным обеспечением. Может быть, вам нужно интегрировать какой-нибудь устаревший плагин jQuery в ваше приложение React? Это случается чаще, чем вы думаете.

Компании и кодовая база развиваются медленно, и унаследованное программное обеспечение имеет ценность, приносящую доход.

5. Определение размера элемента.

Иногда нам нужно определить размеры элемента. Если вы реализуете Tooltip с помощью React Portals, вам необходимо определить, где находится ваш элемент триггера и насколько он велик, чтобы вы могли расположить всплывающую подсказку. Затем вы можете использовать эту информацию, чтобы разместить всплывающую подсказку именно там, где она должна быть.

6. Пересылка ссылок

Когда вы создаете общие компоненты или работаете с библиотекой компонентов, считается хорошей практикой разрешить пересылку ссылок на ваш компонент. Представьте, что вы создаете Button компонент. Если я работаю с вашим компонентом "Значок", я могу отображать Tooltip, когда пользователь наводит курсор на кнопку.

const Button = React.forwardRef((props, ref) => {
  return <button className="btn btn-default" ref={ref} />;
});

Если вы не используете forwardRef со своими функциональными компонентами, вы снижаете удобство использования своих компонентов.

Это лишь некоторые из множества способов, которыми вы можете использовать useRef в своих приложениях React. Я знаю, что документация React говорит нам, что нам не нужно использовать ссылки очень часто, но я обнаружил, что использую их все чаще и чаще. В своей повседневной работе я часто использую ссылки, и как разработчик React я стал лучше с тех пор, как изучил все тонкости React.useRef.

Сообщите нам в комментариях о некоторых интересных проблемах, которые вы решили с useRef!