Preact предоставляет мощный и легковесный механизм управления состоянием и передачи данных между компонентами с помощью контекста. Контекст позволяет компонентам обмениваться информацией без необходимости передавать её через каждый уровень дерева компонентов через пропсы. Этот подход особенно полезен для глобальных настроек приложения, темизации, управления авторизацией и других сценариев, где данные должны быть доступны во многих местах.
Для создания контекста используется функция
createContext из пакета preact или
preact/compat. Она возвращает объект с двумя важными
свойствами: Provider и Consumer.
import { createContext } from 'preact';
const ThemeContext = createContext('light'); // 'light' — значение по умолчанию
Provider предоставляет данные контекста всем
вложенным компонентам. Он принимает проп
value, который определяет текущее значение
контекста.
import { h } from 'preact';
import { ThemeContext } from './ThemeContext';
function App() {
const theme = 'dark';
return (
<ThemeContext.Provider value={theme}>
<Header />
<MainContent />
</ThemeContext.Provider>
);
}
Особенности использования:
value автоматически
вызывает повторный рендер всех потребителей, использующих этот
контекст.Consumer позволяет компоненту подписаться на контекст и получать его текущее значение. В Preact это реализуется через функцию, которая принимает текущее значение и возвращает JSX.
import { h } from 'preact';
import { ThemeContext } from './ThemeContext';
function Header() {
return (
<ThemeContext.Consumer>
{theme => (
<header className={theme === 'dark' ? 'dark-header' : 'light-header'}>
Тема: {theme}
</header>
)}
</ThemeContext.Consumer>
);
}
Ключевые моменты:
В современных версиях Preact можно использовать хуки, что делает работу с контекстом более удобной.
import { useContext } from 'preact/hooks';
import { ThemeContext } from './ThemeContext';
function MainContent() {
const theme = useContext(ThemeContext);
return (
<main className={theme === 'dark' ? 'dark-main' : 'light-main'}>
Контент с текущей темой: {theme}
</main>
);
}
Преимущества использования useContext:
Контекст можно динамически изменять, если передать в Provider
состояние из useState или другой реактивной переменной.
import { h } from 'preact';
import { useState } from 'preact/hooks';
import { ThemeContext } from './ThemeContext';
function App() {
const [theme, setTheme] = useState('light');
return (
<ThemeContext.Provider value={theme}>
<Header />
<button onCl ick={() => setTheme(theme === 'light' ? 'dark' : 'light')}>
Переключить тему
</button>
</ThemeContext.Provider>
);
}
Особенности:
value.Preact позволяет создавать несколько контекстов, включая их друг в друга. При этом каждый потребитель получает значение ближайшего родительского Provider.
const LanguageContext = createContext('ru');
function App() {
return (
<ThemeContext.Provider value="dark">
<LanguageContext.Provider value="en">
<Header />
<MainContent />
</LanguageContext.Provider>
</ThemeContext.Provider>
);
}
В таких случаях компоненты могут одновременно использовать несколько
контекстов через несколько useContext или вложенные
Consumer.
Контекст удобно использовать, но следует учитывать, что каждое изменение значения Provider вызывает рендер всех его потребителей, даже если компонент использует только часть данных. Для оптимизации:
useContext.useMemo, чтобы
не создавать новые объекты на каждый рендер.Контекст в Preact предоставляет мощный и гибкий механизм управления данными, позволяя организовать централизованное состояние и передавать его через дерево компонентов без излишней прокладки пропсов. Комбинация Provider, Consumer и хуков делает работу с контекстом простой и удобной даже в больших приложениях.