Что такое context API и когда его использовать?

Context API — это встроенный механизм React, предназначенный для передачи данных между компонентами, минуя промежуточные уровни дерева. Он позволяет избегать «prop drilling», то есть ситуации, когда одни и те же props необходимо передавать через несколько уровней вложенных компонентов только для того, чтобы они дошли до нужного компонента внизу иерархии. Context предоставляет способ создания глобальных данных, которые могут быть доступны в любом компоненте дерева, если он находится внутри соответствующего провайдера.

Как устроен Context API

Context API состоит из трёх ключевых частей:

  1. React.createContext() — создание объекта контекста.

  2. <Context.Provider> — компонент, предоставляющий данные потомкам.

  3. useContext(Context) — хук для получения доступа к данным из контекста.

Пример создания и использования контекста:

import React, { createContext, useContext, useState } from 'react';
// создаём контекст
const ThemeContext = createContext();
// провайдер контекста
const ThemeProvider = ({ children }) => {
const \[theme, setTheme\] = useState('light');
return (
&lt;ThemeContext.Provider value={{ theme, setTheme }}&gt;
{children}
&lt;/ThemeContext.Provider&gt;
);
};
// компонент-потребитель
const ThemeButton = () => {
const { theme, setTheme } = useContext(ThemeContext);
return (
<Button
title={\`Тема: ${theme}\`}
onPress={() => setTheme(theme === 'light' ? 'dark' : 'light')}
/>
);
};
// использование
const App = () => (
&lt;ThemeProvider&gt;
&lt;ThemeButton /&gt;
&lt;/ThemeProvider&gt;
);

Где применяют Context API

Context удобно использовать, когда необходимо предоставить доступ к общим данным нескольким компонентам, особенно если эти компоненты находятся на разных уровнях вложенности. Наиболее частые сценарии:

  • Текущий пользователь (auth user)

  • Тема оформления (светлая/тёмная)

  • Язык интерфейса (i18n)

  • Настройки приложения

  • Корзина покупок

  • Данные с сервера, актуальные для многих компонентов

Когда использовать, а когда — нет

Context удобен, но не универсален. Он не предназначен для частых изменений или хранения больших объёмов данных, особенно если компоненты, использующие контекст, могут часто перерендериваться.

Использовать Context стоит, если:

  • Данные редко меняются (например, тема оформления или язык)

  • Компоненты находятся глубоко в дереве, и props становятся неэффективными

  • Не требуется глобальное состояние на уровне всего приложения (как в Redux или Zustand)

Лучше не использовать Context, если:

  • Данные изменяются часто (например, инпуты в реальном времени, состояние загрузки, список товаров)

  • Требуется сложная логика управления состоянием (например, асинхронные действия, мидлвары, кэш)

  • Нужно следить за производительностью — каждый потребитель будет перерисован при изменении контекста

Поведение при изменении значений

Когда значение в Provider меняется, все компоненты-потребители контекста перерисовываются, даже если они используют только часть данных. Это может привести к проблемам с производительностью.

Решение:

  • Разделить контексты: вместо одного большого AppContext использовать несколько маленьких (например, ThemeContext, AuthContext, SettingsContext)

  • Мемоизировать значения в Provider, особенно если они содержат функции:

const value = useMemo(() => ({ theme, setTheme }), \[theme\]);
&lt;ThemeContext.Provider value={value}&gt;

Альтернатива Context API

Для более масштабных задач можно использовать:

  • Redux

  • MobX

  • Zustand

  • Recoil

  • Jotai

Они предлагают более эффективные механизмы подписки, селекторы и поддержку асинхронных операций.

Однако во многих приложениях Context оказывается вполне достаточным, особенно если его использовать локально — в рамках отдельного модуля, а не всего приложения.

Советы по использованию

  • Выносите контексты в отдельные модули для читаемости и повторного использования

  • Используйте useMemo и useCallback для минимизации лишних перерендеров

  • Не создавайте сложные вложенные контексты без необходимости

  • Используйте контексты совместно с кастомными хуками, чтобы инкапсулировать логику

Пример кастомного хука:

const useTheme = () => {
const context = useContext(ThemeContext);
if (!context) throw new Error('useTheme must be used within ThemeProvider');
return context;
};

Такой подход делает код более надёжным и читаемым.