useContext
Хук useContext предоставляет способ читать данные из React-контекста без необходимости прокидывать пропсы через каждый уровень компонентного дерева. Это особенно полезно для глобальных данных, таких как тема приложения, язык интерфейса или информация о текущем пользователе.
Как работает контекст
Контекст состоит из двух частей:
- Провайдер (Provider) — компонент, который передаёт значение вниз по дереву.
- Потребитель (Consumer) — любой компонент, который получает это значение с помощью
useContext.
Сначала создаётся контекст:
import { createContext } from 'react';
const ThemeContext = createContext('light'); // 'light' — значение по умолчанию
Затем обёртываем часть приложения в провайдер:
<ThemeContext.Provider value="dark">
<App />
</ThemeContext.Provider>
Внутри любого дочернего компонента можно получить значение:
import { useContext } from 'react';
function Button() {
const theme = useContext(ThemeContext);
return <button className={theme}>Кнопка</button>;
}
Когда использовать
useContext уместен, когда:
- Данные нужны во многих компонентах на разных уровнях вложенности.
- Изменение данных должно вызывать перерисовку всех зависимых компонентов.
- Прокидывание пропсов становится громоздким («пропс-дриллинг»).
Типичные сценарии:
- Темизация
- Мультиязычность
- Аутентификация
- Глобальные настройки
Важные ограничения
Каждый раз, когда значение контекста изменяется, все компоненты, которые его используют, будут перерисованы — даже если они используют только часть данных. Чтобы избежать лишних рендеров:
- Храните в контексте только связанные данные (не объединяйте всё в один глобальный объект).
- Разбивайте контексты по смыслу:
AuthContext,ThemeContext,LanguageContext. - Для сложных значений используйте
useMemo, чтобы сохранять ссылочную стабильность.
Пример плохой практики:
// Не делайте так
<GlobalContext.Provider value={{ user, theme, lang, settings }}>
Лучше:
<UserContext.Provider value={user}>
<ThemeContext.Provider value={theme}>
Это позволяет компонентам подписываться только на то, что им действительно нужно.
Значение по умолчанию
Значение по умолчанию (передаваемое в createContext) используется только если компонент не находится внутри соответствующего Provider. Оно не подходит для динамической инициализации — например, из localStorage. В таких случаях лучше управлять состоянием выше и передавать его в Provider.
Примечание:
useContextне заменяет все остальные хуки. Он решает конкретную проблему — передачу данных «сквозь» дерево. Для локального состояния по-прежнему используйтеuseStateилиuseReducer.