← Назад к вопросам
Зачем нужна библиотека React Context?
2.0 Middle🔥 271 комментариев
#React#Архитектура и паттерны
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI2 апр. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
React Context - управление глобальным состоянием
React Context — это встроенное в React API для передачи данных между компонентами без необходимости пробрасывать props на каждом уровне вложенности. Это решает проблему "prop drilling" (бурления пропсов) в больших приложениях.
Основная проблема, которую решает Context
Prop drilling (бурление пропсов):
// Плохо: нужно пробросить theme через 5 уровней компонентов
<App>
<Layout theme="dark">
<Sidebar theme="dark">
<Menu theme="dark">
<MenuItem theme="dark" />
</Menu>
</Sidebar>
</Layout>
</App>
С Context это решается:
// Хорошо: компоненты могут напрямую получить значение
<ThemeProvider value="dark">
<App />
</ThemeProvider>
Как работает Context
Создание контекста:
import { createContext } from 'react';
const ThemeContext = createContext('light');
Provider - предоставляет значение:
export function ThemeProvider({ children, value }) {
return (
<ThemeContext.Provider value={value}>
{children}
</ThemeContext.Provider>
);
}
Потребитель значения через useContext:
import { useContext } from 'react';
function Button() {
const theme = useContext(ThemeContext);
return (
<button className={`button-${theme}`}>
Нажми меня
</button>
);
}
Практический пример: приложение с темой
Создание контекста:
import { createContext, useState } from 'react';
const ThemeContext = createContext();
export function ThemeProvider({ children }) {
const [theme, setTheme] = useState('light');
const toggleTheme = () => {
setTheme(prev => prev === 'light' ? 'dark' : 'light');
};
return (
<ThemeContext.Provider value={{ theme, toggleTheme }}>
{children}
</ThemeContext.Provider>
);
}
export function useTheme() {
const context = useContext(ThemeContext);
if (!context) {
throw new Error('useTheme должен быть использован внутри ThemeProvider');
}
return context;
}
Использование в приложении:
import { useTheme } from './ThemeContext';
function Header() {
const { theme, toggleTheme } = useTheme();
return (
<header className={`header-${theme}`}>
<button onClick={toggleTheme}>
Переключить на {theme === 'light' ? 'тёмную' : 'светлую'} тему
</button>
</header>
);
}
function App() {
return (
<ThemeProvider>
<Header />
<main>Содержимое</main>
</ThemeProvider>
);
}
Несколько Context'ов вместе
Комбинирование нескольких провайдеров:
function App() {
return (
<ThemeProvider>
<LanguageProvider>
<AuthProvider>
<MainApp />
</AuthProvider>
</LanguageProvider>
</ThemeProvider>
);
}
// Или с помощью compose функции
function combineProviders(...providers) {
return ({ children }) =>
providers.reduceRight((child, Provider) =>
<Provider>{child}</Provider>,
children
);
}
const AppProviders = combineProviders(
ThemeProvider,
LanguageProvider,
AuthProvider
);
function App() {
return (
<AppProviders>
<MainApp />
</AppProviders>
);
}
Когда использовать Context
Хорошие примеры:
- Аутентификация (текущий пользователь, токен)
- Тема приложения (светлая/тёмная)
- Язык интерфейса (локализация)
- Модальные окна и уведомления
- Глобальные настройки приложения
Плохие примеры:
- Часто меняющееся состояние (leads to re-renders)
- Большие объемы данных
- Состояние, которое меняется на каждый render
- Простые данные для одного компонента
Context vs Redux vs Zustand
| Характеристика | Context | Redux | Zustand |
|---|---|---|---|
| Встроен в React | Да | Нет | Нет |
| Сложность | Простой | Сложный | Очень простой |
| Производительность | Хорошая | Отличная | Отличная |
| DevTools | Нет | Да | Да |
| Асинхронные операции | Нужны хуки | Middleware | Просто |
| Размер бандла | 0 КБ | +60 КБ | +2 КБ |
Оптимизация производительности с Context
Проблема: лишние re-renders
// Плохо: весь компонент перерендерится
function App() {
const [theme, setTheme] = useState('light');
const [notifications, setNotifications] = useState([]);
return (
<ThemeContext.Provider value={{ theme, setTheme }}>
<NotificationsContext.Provider value={{ notifications, setNotifications }}>
<Header />
</NotificationsContext.Provider>
</ThemeContext.Provider>
);
}
Решение: разделить контексты
// Хорошо: каждый контекст отдельный
<ThemeProvider>
<NotificationsProvider>
<Header />
</NotificationsProvider>
</ThemeProvider>
Использование useMemo для оптимизации:
function ThemeProvider({ children }) {
const [theme, setTheme] = useState('light');
const value = useMemo(() => ({ theme, setTheme }), [theme]);
return (
<ThemeContext.Provider value={value}>
{children}
</ThemeContext.Provider>
);
}
Основные преимущества
- Избегаем prop drilling — не нужно пробрасывать пропсы через много уровней
- Чистый код — компоненты не знают о внутренней структуре
- Переиспользуемость — контекст можно использовать в разных местах приложения
- Встроено в React — не нужна дополнительная библиотека
- Простота — легко начать использовать
Основные ограничения
- Производительность — при частых обновлениях переренды все потребители
- Нет DevTools — сложнее дебажить
- Нет middleware — сложнее обрабатывать асинхронные операции
- Дублирование кода — нужна своя обработка состояния
Лучшие практики
- Используй кастомный хук (useTheme) для доступа к контексту
- Раздели контексты по доменам (Auth, Theme, Language)
- Оборачивай контекст в Provider компонент
- Используй useMemo для оптимизации
- Помни о производительности при частых изменениях