Зарегистрируйтесь для доступа к 15+ бесплатным курсам по программированию с тренажером

Хук useContext JS: React Hooks

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

Хук useContext() позволяет использовать контекст внутри компонента. Для этого нужно выполнить три действия:

  1. Инициализировать контекст в том же месте, где инициализируется приложение

    // Параметром передается значение по умолчанию
    // Имя контекста выбирается произвольно
    const UserContext = React.createContext({});
    
  2. Подключить провайдер и передать данные в контекст через пропс value.

    // user – данные которые лежат внутри контекста
    <UserContext.Provider value={user}>
      <MyComponent />
    </UserContext.Provider>
    
  3. Получить данные контекста

    import React, { useContext } from 'react';
    
    const MyComponent = () => {
      // Возвращает контекст целиком
      const user = useContext(UserContext);
    
      return <h1>{user.name}</h1>;
    }
    

Вот другой пример контекста, в котором хранится текущая тема:

const themes = {
  light: {
    foreground: '#000000',
    background: '#eeeeee',
  },
  dark: {
    foreground: '#ffffff',
    background: '#222222',
  },
};

const ThemeContext = React.createContext(
  themes.dark, // значение по умолчанию
);

И где-то внутри приложения:

<ThemeContext.Provider value={/* текущая тема */}>
  <Content />
</ThemeContext.Provider>

Внутри контекста может хранится как примитивное значение, так и объект. Изменение содержимого такого объекта никак не отслеживается React, поэтому не приводит к перерендеру. Но если заменить сам объект, то из-за изменившейся ссылки React узнает об изменении и выполнит перерисовку компонентов внутри провайдера.

Иногда возникает ситуация, когда в контексте нужно хранить динамические данные. Например, при авторизации. Когда пользователь авторизован, мы должны сохранить какие-то данные, чтобы пользователю предоставлялись дополнительные функции. Сам по себе контекст для этого ничего не предоставляет, но можно передать в контекст методы для манипулирования данными, а сами данные хранить с помощью useState(). Более продвинутый вариант - это создать провайдер в отдельном компоненте. Так мы сможем изолировать данные от всего приложения, а в компоненты передавать интерфейс для взаимодействия с данными.

Для этого создадим контекст в отдельном модуле, чтобы все компоненты могли его импортировать:

// ThemeContext.js

import { createContext } from 'react';

export default createContext({
  themes: {},
  theme: {},
  setTheme: () => {},
});

Создаём отдельный компонент провайдера:

import ThemeContext from './ThemeContext.js';

const ThemeProvider = ({ children }) => {
  const [theme, setTheme] = useState(themes.dark);

  const setLightTheme = () => setTheme(themes.light);

  const setDarkTheme = () => setTheme(themes.dark);

  return (
    <ThemeContext.Provider value={{ theme, setLightTheme, setDarkTheme, themes }}>
      {children}
    </ThemeContext.Provider>
  );
};

И внутри приложения используем провайдер как обычный компонент:

<ThemeProvider>
  <MyComponent />
</ThemeProvider>

В самом компоненте теперь можно импортировать контекст и использовать функции из провайдера для изменения состояния в контексте:

import React, { useContext } from 'react';
import ThemeContext from './ThemeContext.js';

const MyComponent = () => {
  const { setLightTheme } = useContext(ThemeContext);

  return <button onClick={() => setLightTheme()}>Включить светлую тему</button>;
}

Контекст - удобный механизм для некоторых особых ситуаций, но он не должен становиться основным способом передачи данных внутрь приложения. Такой соблазн появляется у многих, кто использует его впервые. Главная проблема контекстов – связывание компонентов с глобальными данным, а это затрудняет их повторное использование в других ситуациях.


Дополнительные материалы

  1. Использование хука useContext
  2. Механизм контекстов

Аватары экспертов Хекслета

Остались вопросы? Задайте их в разделе «Обсуждение»

Вам ответят команда поддержки Хекслета или другие студенты.

Ошибки, сложный материал, вопросы >
Нашли опечатку или неточность?

Выделите текст, нажмите ctrl + enter и отправьте его нам. В течение нескольких дней мы исправим ошибку или улучшим формулировку.

Что-то не получается или материал кажется сложным?

Загляните в раздел «Обсуждение»:

  • задайте вопрос. Вы быстрее справитесь с трудностями и прокачаете навык постановки правильных вопросов, что пригодится и в учёбе, и в работе программистом;
  • расскажите о своих впечатлениях. Если курс слишком сложный, подробный отзыв поможет нам сделать его лучше;
  • изучите вопросы других учеников и ответы на них. Это база знаний, которой можно и нужно пользоваться.

Об обучении на Хекслете

Для полного доступа к курсу нужен базовый план

Базовый план откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.

Получить доступ
900
упражнений
2000+
часов теории
3200
тестов

Открыть доступ

Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно.

  • 130 курсов, 2000+ часов теории
  • 900 практических заданий в браузере
  • 360 000 студентов
Даю согласие на обработку персональных данных, соглашаюсь с «Политикой конфиденциальности» и «Условиями оказания услуг»

Наши выпускники работают в компаниях:

Логотип компании Альфа Банк
Логотип компании Aviasales
Логотип компании Yandex
Логотип компании Tinkoff
Рекомендуемые программы

С нуля до разработчика. Возвращаем деньги, если не удалось найти работу.

Иконка программы Фронтенд-разработчик
Профессия
Разработка фронтенд-компонентов веб-приложений
25 мая 10 месяцев

Используйте Хекслет по максимуму!

  • Задавайте вопросы по уроку
  • Проверяйте знания в квизах
  • Проходите практику прямо в браузере
  • Отслеживайте свой прогресс

Зарегистрируйтесь или войдите в свой аккаунт

Даю согласие на обработку персональных данных, соглашаюсь с «Политикой конфиденциальности» и «Условиями оказания услуг»