useRef и useContext

useRef: управление ссылками на элементы и сохранение состояния

useRef — это хук, предоставляемый React, который позволяет создавать мутабельный объект, сохраняющийся между рендерами компонента. Основные сферы применения:

  1. Сохранение ссылки на DOM-элемент useRef создаёт объект с полем current, которое может хранить ссылку на HTML-элемент. Это полезно для прямого взаимодействия с DOM, например, для установки фокуса или измерения размеров элемента.

    import { useRef, useEffect } from 'react';
    
    function InputFocus() {
      const inputRef = useRef(null);
    
      useEffect(() => {
        inputRef.current.focus();
      }, []);
    
      return <input ref={inputRef} type="text" />;
    }

    В этом примере inputRef.current ссылается на сам элемент <input> после рендера.

  2. Хранение мутабельного значения между рендерами Значение в ref не вызывает повторный рендер при изменении, что делает его идеальным для хранения данных, которые не должны напрямую влиять на UI.

    function Timer() {
      const count = useRef(0);
    
      useEffect(() => {
        const interval = setInterval(() => {
          count.current += 1;
          console.log(count.current);
        }, 1000);
    
        return () => clearInterval(interval);
      }, []);
    
      return <div>Счётчик работает в консоли</div>;
    }
  3. Отличие от состояния (useState)

    • useState вызывает ререндер при изменении значения.
    • useRef сохраняет данные без повторного рендера.

useContext: доступ к глобальному состоянию компонента

useContext предоставляет возможность подписаться на React Context внутри функционального компонента и получать его текущее значение.

  1. Создание контекста Контекст создаётся с помощью React.createContext и может содержать любое значение: объекты, функции, строки и т.д.

    import { createContext } from 'react';
    
    const ThemeContext = createContext('light');

    Здесь 'light' — значение по умолчанию, которое используется, если компонент не обернут в соответствующий Provider.

  2. Использование провайдера Provider оборачивает компоненты, которым необходимо предоставить доступ к контексту.

    import { useState } from 'react';
    
    function App() {
      const [theme, setTheme] = useState('dark');
    
      return (
        <ThemeContext.Provider value={{ theme, setTheme }}>
          <Toolbar />
        </ThemeContext.Provider>
      );
    }
  3. Доступ к контексту через useContext Внутри компонента можно получить текущее значение контекста без необходимости пробрасывать props.

    import { useContext } from 'react';
    
    function Toolbar() {
      const { theme, setTheme } = useContext(ThemeContext);
    
      return (
        <div>
          <p>Текущая тема: {theme}</p>
          <button onCl ick={() => setTheme(theme === 'dark' ? 'light' : 'dark')}>
            Переключить тему
          </button>
        </div>
      );
    }
  4. Особенности работы useContext

    • Компонент автоматически подписывается на изменения контекста.
    • При изменении значения контекста происходит ререндер всех подписанных компонентов.
    • useContext не принимает динамический ключ; значение контекста должно быть известным на момент рендера.

Совместное использование useRef и useContext

Часто useRef и useContext применяются вместе для оптимизации взаимодействия с DOM и глобальными состояниями:

function AutoFocusInput() {
  const inputRef = useRef(null);
  const { theme } = useContext(ThemeContext);

  useEffect(() => {
    inputRef.current.focus();
  }, []);

  return <input ref={inputRef} style={{ background: theme === 'dark' ? '#333' : '#fff' }} />;
}

Здесь useRef управляет фокусом элемента, а useContext — стилем, зависящим от глобальной темы.

Практические советы

  • useRef полезен для хранения таймеров, интервалов, предыдущих значений props.
  • useContext удобен для тем, настроек приложения, глобальных функций и состояний, которые нужно использовать в разных компонентах.
  • Избегать чрезмерного использования контекста для часто обновляемых данных, так как это может привести к частым рендерам большого числа компонентов.
  • useRef не заменяет состояние, когда требуется реактивное обновление UI.

useRef и useContext являются базовыми инструментами React для управления состоянием и ссылками на элементы, обеспечивая оптимизацию и удобство работы с компонентами без усложнения архитектуры.