Что такое Context API и как его использовать?react-41

Основная концепция

Context API — это встроенная в React система управления состоянием (state management), которая позволяет передавать данные через дерево компонентов без необходимости явно передавать пропсы (props) на каждом уровне (пропс дриллинг).


Когда использовать Context API?

  1. Глобальные данные: Тема приложения, аутентификация, локализация
  2. Часто используемые данные: Настройки пользователя, кэш данных
  3. Избегание пропс дриллинга: Когда нужно передавать данные через множество уровней компонентов

Базовое использование

1. Создание контекста

import { createContext } from 'react';

const ThemeContext = createContext('light'); // Значение по умолчанию

2. Поставщик контекста

function App() {
  return (
    <ThemeContext.Provider value="dark">
      <Toolbar />
    </ThemeContext.Provider>
  );
}

3. Потребление контекста

Способ 1: useContext Hook

function Button() {
  const theme = useContext(ThemeContext);
  return <button className={theme}>Кнопка</button>;
}

Способ 2: Context.Consumer

function Button() {
  return (
    <ThemeContext.Consumer>
      {theme => <button className={theme}>Кнопка</button>}
    </ThemeContext.Consumer>
  );
}

Продвинутые паттерны

1. Динамический контекст

function App() {
  const [theme, setTheme] = useState('dark');

  const toggleTheme = () => {
    setTheme(prev => prev === 'dark' ? 'light' : 'dark');
  };

  return (
    <ThemeContext.Provider value={{ theme, toggleTheme }}>
      <Toolbar />
    </ThemeContext.Provider>
  );
}

2. Кастомный провайдер

function ThemeProvider({ children }) {
  const [theme, setTheme] = useState('light');

  const value = {
    theme,
    toggleTheme: () => setTheme(prev => prev === 'light' ? 'dark' : 'light')
  };

  return (
    <ThemeContext.Provider value={value}>
      {children}
    </ThemeContext.Provider>
  );
}

// Использование
<ThemeProvider>
  <App />
</ThemeProvider>

3. Множественные контексты


function App() {
  return (
    <ThemeContext.Provider value="dark">
      <UserContext.Provider value={{ name: 'John' }}>
        <Content />
      </UserContext.Provider>
    </ThemeContext.Provider>
  );
}

Оптимизация производительности

1. Мемоизация значения контекста

function App() {
  const [user, setUser] = useState({ name: 'John', age: 30 });

  const value = useMemo(() => ({ user, setUser }), [user]);

  return (
    <UserContext.Provider value={value}>
      <Content />
    </UserContext.Provider>
  );
}

2. Разделение контекстов

Лучше иметь несколько специализированных контекстов, чем один большой:

// Плохо:
<UserContext.Provider value={{ user, settings, preferences }}>

// Хорошо:
<UserContext.Provider value={user}>
  <SettingsContext.Provider value={settings}>
    <PreferencesContext.Provider value={preferences}>

Ограничения и лучшие практики

  1. Не для часто изменяющихся данных: Context API не оптимизирован для высокочастотных обновлений
  2. Избегайте глубоких вложений: Слишком много Provider-ов ухудшает читаемость
  3. Комбинируйте с useReducer: Для сложного состояния
    const [state, dispatch] = useReducer(reducer, initialState);
    return (
      <StateContext.Provider value={state}>
        <DispatchContext.Provider value={dispatch}>
    

Сравнение с другими решениями

Характеристика Context API Redux MobX
Встроен в React
Кривая обучения Низкая Средняя Высокая
Подходит для Средних приложений Крупных приложений Крупных приложений
DevTools


Типичные ошибки

  1. Ненужные ререндеры: Передача нового объекта в value без useMemo
    <UserContext.Provider value={{ user, setUser }}> // ❌ Создает новый объект при каждом рендере
    
  2. Злоупотребление: Использование для локального состояния компонента
  3. Слишком большой контекст: Один контекст для всего приложения

Резюмируем

  1. Context API решает проблему пропс дриллинга
  2. Состоит из createContext, Provider и Consumer/useContext
  3. Оптимизируйте с помощью useMemo и разделения контекстов
  4. Не заменяет Redux/MobX для сложных сценариев
  5. Идеален для среднечастотных глобальных данных

Для глубокой интеграции рассмотрите кастомные хуки + контекст.