useContext для глобального состояния
Создавайте Context, оборачивайте поддерево его Provider и получайте значение через useContext, чтобы делиться состоянием темы или авторизации без передачи props через каждый компонент.
«useContext для глобального состояния» — бесплатный урок Frontend Academy на CoddyKit. Это урок 1 из 4. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения Frontend Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс Frontend Academy содержит 4 уроков всего.
Проблема передачи свойств через цепочку
Передача свойств через цепочку означает передачу данных через множество промежуточных компонентов, которые ими не пользуются, лишь чтобы достичь глубоко вложенного дочернего компонента. Контекст решает эту проблему, делая значение доступным любому компоненту в дереве без явной передачи.
Создание контекста
createContext(defaultValue) создаёт объект контекста. Значение по умолчанию используется, когда компонент читает контекст без соответствующего провайдера выше него.
import { createContext } from 'react';
interface ThemeContextType {
theme: 'light' | 'dark';
toggleTheme: () => void;
}
const ThemeContext = createContext<ThemeContextType>({
theme: 'light',
toggleTheme: () => {}
});Предоставление контекста
Оберните часть дерева, которой нужен контекст, в провайдер. Все компоненты внутри могут прочитать значение контекста.
function ThemeProvider({ children }: { children: React.ReactNode }) {
const [theme, setTheme] = useState<'light' | 'dark'>('light');
const toggleTheme = () => setTheme(t => t === 'light' ? 'dark' : 'light');
return (
<ThemeContext.Provider value={{ theme, toggleTheme }}>
{children}
</ThemeContext.Provider>
);
}
// In app root:
<ThemeProvider>
<App />
</ThemeProvider>Использование useContext
Любой компонент внутри Provider может получить значение контекста с помощью useContext(ThemeContext). Передавать что-либо через пропсы не нужно.
function ThemeToggle() {
const { theme, toggleTheme } = useContext(ThemeContext);
return (
<button onClick={toggleTheme}>
Switch to {theme === 'light' ? 'dark' : 'light'} mode
</button>
);
}Пользовательский хук-обёртка для useContext
Экспортируйте пользовательский хук, который внутри вызывает useContext. Это чище, чем напрямую предоставлять контекст, и позволяет добавить проверку.
function useTheme() {
const ctx = useContext(ThemeContext);
if (!ctx) throw new Error('useTheme must be used inside ThemeProvider');
return ctx;
}
// Usage:
const { theme } = useTheme();Повторный рендеринг при изменении контекста
Когда значение Provider изменяется, все потребители выполняют повторный рендеринг. Если значение является объектом, новая ссылка на объект при каждом рендеринге заставит всех потребителей выполнить повторный рендеринг. Используйте useMemo для мемоизации значения и предотвращения этого.
const value = useMemo(
() => ({ theme, toggleTheme }),
[theme] // toggleTheme is stable if created with useCallback
);
<ThemeContext.Provider value={value}>Когда использовать контекст
Подходит для: темы, локали, аутентифицированного пользователя, флагов функций, системы уведомлений. Не подходит для: частых обновлений (при каждом нажатии клавиши), большого сложного состояния (вместо этого используйте хранилище).
Несколько контекстов
Вы можете использовать несколько независимых контекстов. Сохраняйте их узконаправленными: AuthContext для аутентификации, ThemeContext для темы. Избегайте единого огромного контекста, который хранит всё.
Контекст и Redux
Контекст встроен в React и подходит для глобальных данных, которые изменяются нечасто. Redux/Zustand/Pinia лучше подходят для сложного состояния с многочисленными обновлениями, отладкой с перемещением во времени или потребностью в промежуточном программном обеспечении.
Шаблон контекста аутентификации
Распространённый шаблон: AuthContext, который хранит текущего пользователя и методы аутентификации. Компоненты-потребители получают пользователя без последовательного проброса пропсов.
interface AuthContext {
user: User | null;
login: (creds: Credentials) => Promise<void>;
logout: () => void;
}
const AuthCtx = createContext<AuthContext | null>(null);
export const useAuth = () => {
const ctx = useContext(AuthCtx);
if (!ctx) throw new Error('Outside AuthProvider');
return ctx;
};Контекст и TypeScript
Типизируйте контекст с помощью интерфейса. Используйте null как начальное значение и выбрасывайте ошибку в пользовательском хуке, если значение равно null. Это не позволяет состоянию «контекст потреблён вне провайдера» молча возникнуть, хотя оно невозможно.
Производительность: memo + контекст
Компоненты, обёрнутые в React.memo, не выполняют повторный рендеринг, если их пропсы не изменились. Если результат работы потребителя контекста зависит только от части контекста, разделите контекст или используйте шаблоны с селекторами, чтобы избежать ненужного повторного рендеринга.
Быстрая проверка
Что возвращает useContext(MyContext), если вызвать его внутри компонента, над которым нет Provider?
Краткое повторение: useContext
createContext создаёт контекст со значением по умолчанию. Оберните дерево в Provider, чтобы передать значение. useContext считывает значение в любом месте внутри него. Пользовательские хуки оборачивают useContext для проверки. Мемоизируйте значение Provider, чтобы предотвратить ненужный повторный рендеринг. Используйте контекст для глобальных данных, которые изменяются нечасто, например темы и аутентификации.
Изучай HTML с ИИ-репетитором — бесплатно
Пиши и запускай код прямо в браузере, получай мгновенную помощь от ИИ-репетитора 24/7 и продолжи учиться на сайте или в приложении.
- Курсы
- 41
- Уроки
- 163
Часто задаваемые вопросы
Урок «useContext для глобального состояния» бесплатный?
Да — полный текст урока «useContext для глобального состояния» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс Frontend Academy, подпишись на CoddyKit PRO. Курс Frontend Academy содержит 4 уроков всего.
Чему я научусь в уроке «useContext для глобального состояния»?
Создавайте Context, оборачивайте поддерево его Provider и получайте значение через useContext, чтобы делиться состоянием темы или авторизации без передачи props через каждый компонент. Ты практикуешь Frontend Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать Frontend Academy?
Предыдущий опыт не требуется. Frontend Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 1 из 4.
Сколько времени занимает урок «useContext для глобального состояния»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке Frontend Academy?
Да. Каждый урок Frontend Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- useContext для глобального состояния
- useReducer для сложного состояния
- useMemo и useCallback для производительности
- Пользовательские хуки: выделение повторно используемой логики