Работа с данными — одна из самых важных задач в React. Когда ваши компоненты начинают обмениваться данными, это может превратиться в настоящий хаос, особенно если данные нужно передать через несколько уровней компонентов.
Вот где приходит на помощь Context API, упрощая жизнь разработчикам. Сегодня мы разберём, как работает контекст, когда его стоит использовать, и создадим пример с темой оформления (тёмная/светлая).
Что такое Context API и зачем он нужен?
Контекст в React — это механизм для передачи данных через дерево компонентов, минуя пропсы на каждом уровне. Он отлично подходит, когда одни и те же данные требуются многим компонентам, но передача через пропсы становится громоздкой.
Проблема, которую решает контекст
Допустим, у нас есть глобальная тема (например, светлая или тёмная). Эта тема нужна:
- На верхнем уровне, чтобы стилизовать шапку.
- В середине дерева, чтобы настроить кнопки.
- Внизу, чтобы изменить фон карточек.
Передача темы через пропсы превращается в кошмар:
<Parent theme={theme}>
<Child theme={theme}>
<GrandChild theme={theme} />
</Child>
</Parent>
Это называется проблемой пропс-дриллинга (props drilling). Она делает код неудобным и трудным для поддержки.
Как работает Context API?
Контекст позволяет:
- Определить глобальное значение (например, текущую тему).
- Предоставить это значение всем компонентам в дереве.
- Использовать его, где нужно, без явной передачи через пропсы.
Создание контекста и использование useContext
1. Создание контекста
Контекст создаётся с помощью React.createContext:
const ThemeContext = React.createContext();
2. Провайдер (Provider)
Чтобы сделать контекст доступным, нужно обернуть часть дерева компонентов в ThemeContext.Provider:
<ThemeContext.Provider value={theme}>
<App />
</ThemeContext.Provider>
3. Использование контекста
Компоненты внутри Provider могут получить доступ к данным контекста с помощью хука useContext:
const theme = useContext(ThemeContext);
Когда использовать контекст
Контекст полезен, но подходит не для всех случаев.
Когда использовать:
- Глобальные данные: Тема оформления, язык приложения, пользовательские настройки.
- Глобальное состояние: Аутентификация, текущий пользователь.
Когда НЕ использовать:
- Если данные нужны только одному или двум компонентам. В таком случае пропсы проще и понятнее.
- Для часто изменяющихся данных. Контекст не подходит для данных, которые обновляются очень часто (например, координаты мыши), так как каждое обновление контекста приводит к обновлению всех компонентов, которые его используют.
Практика: Тема оформления (тёмная/светлая)
Теперь создадим приложение, где пользователь может переключать тему (тёмную или светлую) с помощью контекста.
Шаг 1: Создаём контекст
В App.jsx создайте контекст:
import React, { useState, createContext, useContext } from 'react';
// Создаём контекст
const ThemeContext = createContext();
function App() {
const [isDarkMode, setIsDarkMode] = useState(false); // Управляем состоянием темы
const toggleTheme = () => setIsDarkMode(!isDarkMode);
const theme = {
isDarkMode,
toggleTheme,
};
return (
<ThemeContext.Provider value={theme}>
<Main />
</ThemeContext.Provider>
);
}
function Main() {
return (
<div>
<Header />
<Content />
</div>
);
}
export default App;
Здесь:
- Мы создаём контекст ThemeContext.
- Передаём в него объект theme, который содержит текущую тему (isDarkMode) и функцию для переключения темы (toggleTheme).
Шаг 2: Используем контекст в Header
Создадим компонент Header, который отображает кнопку переключения темы:
function Header() {
const { isDarkMode, toggleTheme } = useContext(ThemeContext);
return (
<header
style={{
padding: '10px 20px',
backgroundColor: isDarkMode ? '#333' : '#f9f9f9',
color: isDarkMode ? '#fff' : '#000',
textAlign: 'center',
}}
>
<h1>Тема: {isDarkMode ? 'Тёмная' : 'Светлая'}</h1>
<button
onClick={toggleTheme}
style={{
padding: '10px 20px',
backgroundColor: isDarkMode ? '#555' : '#ddd',
border: 'none',
borderRadius: '5px',
cursor: 'pointer',
}}
>
Переключить тему
</button>
</header>
);
}
Здесь:
- Мы используем useContext(ThemeContext), чтобы получить текущую тему и функцию переключения.
- Динамически стилизуем фон и текст в зависимости от isDarkMode.
Шаг 3: Стилизуем контент
Создадим компонент Content, который изменяет фон и текст в зависимости от темы:
function Content() {
const { isDarkMode } = useContext(ThemeContext);
return (
<main
style={{
padding: '20px',
backgroundColor: isDarkMode ? '#222' : '#fff',
color: isDarkMode ? '#ddd' : '#000',
minHeight: '200px',
textAlign: 'center',
}}
>
<p>
Это пример использования <strong>Context API</strong> для управления темой оформления.
</p>
</main>
);
}
Шаг 4: Запускаем приложение
Запустите приложение:
npm run dev
В браузере вы увидите кнопку для переключения темы. Нажимайте на неё, и приложение будет динамически менять стиль.
Итоговый код
Вот итоговый файл App.jsx:
import React, { useState, createContext, useContext } from 'react';
const ThemeContext = createContext();
function App() {
const [isDarkMode, setIsDarkMode] = useState(false);
const toggleTheme = () => setIsDarkMode(!isDarkMode);
const theme = {
isDarkMode,
toggleTheme,
};
return (
<ThemeContext.Provider value={theme}>
<Main />
</ThemeContext.Provider>
);
}
function Main() {
return (
<div>
<Header />
<Content />
</div>
);
}
function Header() {
const { isDarkMode, toggleTheme } = useContext(ThemeContext);
return (
<header
style={{
padding: '10px 20px',
backgroundColor: isDarkMode ? '#333' : '#f9f9f9',
color: isDarkMode ? '#fff' : '#000',
textAlign: 'center',
}}
>
<h1>Тема: {isDarkMode ? 'Тёмная' : 'Светлая'}</h1>
<button
onClick={toggleTheme}
style={{
padding: '10px 20px',
backgroundColor: isDarkMode ? '#555' : '#ddd',
border: 'none',
borderRadius: '5px',
cursor: 'pointer',
}}
>
Переключить тему
</button>
</header>
);
}
function Content() {
const { isDarkMode } = useContext(ThemeContext);
return (
<main
style={{
padding: '20px',
backgroundColor: isDarkMode ? '#222' : '#fff',
color: isDarkMode ? '#ddd' : '#000',
minHeight: '200px',
textAlign: 'center',
}}
>
<p>
Это пример использования <strong>Context API</strong> для управления темой оформления.
</p>
</main>
);
}
export default App;
Итоги
Сегодня мы разобрались:
- Что такое Context API и как он помогает избежать пропс-дриллинга.
- Как использовать контекст с помощью createContext и useContext.
- Когда контекст полезен, а когда стоит выбрать другой подход.
На практике мы создали приложение с переключением темы оформления. Теперь вы можете использовать контекст для управления глобальными данными, такими как язык, авторизация или настройки.
Комментарии
0