Контекст в Preact предоставляет механизм передачи данных через дерево компонентов без необходимости вручную прокидывать их через каждый уровень пропсов. Это особенно важно при работе с глобальными состояниями, темами, настройками пользователя и другими данными, которые должны быть доступны в разных частях приложения.
Для создания контекста используется функция
createContext из пакета preact:
import { createContext } from 'preact';
const ThemeContext = createContext('light');
Здесь 'light' — значение по умолчанию, которое будет
использоваться, если компонент-потребитель не обернут в
Provider. Контекст можно назвать любым образом, исходя из
его предназначения: UserContext, AuthContext,
SettingsContext и т.д.
Провайдер (Provider) является компонентом,
предоставляющим значение контекста всем дочерним компонентам:
import { h } from 'preact';
import { useState } from 'preact/hooks';
function App() {
const [theme, setTheme] = useState('dark');
return (
<ThemeContext.Provider value={{ theme, setTheme }}>
<Toolbar />
</ThemeContext.Provider>
);
}
Ключевые моменты:
value задаёт текущее значение, которое будет
доступно потребителям.value вызывает повторный рендер всех
компонентов, использующих этот контекст.Для использования контекста в функциональных компонентах применяется
хук useContext:
import { useContext } from 'preact/hooks';
function Toolbar() {
const { theme, setTheme } = useContext(ThemeContext);
return (
<div className={`toolbar toolbar-${theme}`}>
<button onCl ick={() => setTheme(theme === 'dark' ? 'light' : 'dark')}>
Переключить тему
</button>
</div>
);
}
Особенности:
useContext возвращает текущее значение контекста.Provider, используется значение по умолчанию.Provider автоматически
обновляет все компоненты, использующие этот контекст.Чрезмерное использование контекста может вызвать лишние рендеры компонентов. Для оптимизации рекомендуется:
value
передаётся как объект, использовать useMemo:import { useMemo } from 'preact/hooks';
function App() {
const [theme, setTheme] = useState('dark');
const value = useMemo(() => ({ theme, setTheme }), [theme]);
return (
<ThemeContext.Provider value={value}>
<Toolbar />
</ThemeContext.Provider>
);
}
В Preact классовые компоненты также могут использовать контекст через
статическое свойство contextType:
import { Component } from 'preact';
class Toolbar extends Component {
render() {
const { theme, setTheme } = this.context;
return (
<div className={`toolbar toolbar-${theme}`}>
<button onCl ick={() => setTheme(theme === 'dark' ? 'light' : 'dark')}>
Переключить тему
</button>
</div>
);
}
}
Toolbar.contextType = ThemeContext;
this.context.Контекст в Preact поддерживает вложенность. Значение контекста определяется ближайшим провайдером сверху по дереву компонентов:
<ThemeContext.Provider value={{ theme: 'light' }}>
<Toolbar />
<ThemeContext.Provider value={{ theme: 'dark' }}>
<Sidebar />
</ThemeContext.Provider>
</ThemeContext.Provider>
Toolbar получит theme: 'light', а
Sidebar — theme: 'dark'.Для передачи нескольких независимых данных часто создают отдельные контексты:
<UserContext.Provider value={user}>
<ThemeContext.Provider value={{ theme, setTheme }}>
<Dashboard />
</ThemeContext.Provider>
</UserContext.Provider>
В компоненте можно использовать несколько
useContext:
const user = useContext(UserContext);
const { theme } = useContext(ThemeContext);
Такой подход повышает читаемость кода и упрощает тестирование.
Контекст в Preact является мощным инструментом для управления состоянием и глобальными данными. Правильная организация провайдеров, мемоизация значений и грамотное разделение контекстов позволяет создавать масштабируемые, производительные и поддерживаемые приложения.