Haunted — это лёгкая библиотека для создания веб-компонентов с использованием реактивного состояния и хуков, вдохновлённых React. Одной из ключевых возможностей для построения масштабируемых приложений является контекст, который позволяет компонентам обмениваться данными без необходимости пробрасывать их через каждый уровень иерархии.
Контекст в Haunted работает аналогично контексту в React. Он позволяет:
Контекст состоит из двух частей:
Для создания контекста используется функция
createContext. Она возвращает объект с полями
Provider и useContext.
import { createContext, html, component, useState } from 'haunted';
const ThemeContext = createContext();
function ThemeProvider({ children }) {
const [theme, setTheme] = useState('light');
const toggleTheme = () => setTheme(theme === 'light' ? 'dark' : 'light');
return html`
<${ThemeContext.Provider} .value=${{ theme, toggleTheme }}>
${children}
<//>
`;
}
customElements.define('theme-provider', component(ThemeProvider));
Пояснения:
createContext() создаёт контекст, который можно
использовать в любом компоненте.ThemeContext.Provider оборачивает дочерние компоненты и
предоставляет им объект состояния value.value может быть любым: объектом, строкой,
функцией.Компоненты, находящиеся внутри провайдера, могут получить доступ к
контексту с помощью хука useContext.
import { useContext } from 'haunted';
function ThemeSwitcher() {
const { theme, toggleTheme } = useContext(ThemeContext);
return html`
<button @click=${toggleTheme}>
Сменить тему (текущая: ${theme})
</button>
`;
}
customElements.define('theme-switcher', component(ThemeSwitcher));
Особенности:
useContext автоматически подписывает компонент на
изменения контекста. Если value изменится, компонент
перерисуется.Provider.Haunted позволяет использовать вложенные провайдеры для создания локальных контекстов с переопределёнными значениями. При этом внутренний провайдер перекрывает значение внешнего для дочерних компонентов.
function App() {
return html`
<${ThemeProvider}>
<theme-switcher></theme-switcher>
<${ThemeContext.Provider} .value=${{ theme: 'custom', toggleTheme: () => {} }}>
<theme-switcher></theme-switcher>
<//>
<//>
`;
}
В этом примере первый theme-switcher использует значение
'light' или 'dark', а второй —
'custom'.
Для сложных приложений часто требуется, чтобы контекст содержал
реактивное состояние, которое изменяется динамически.
Haunted позволяет использовать любые хуки внутри провайдера, включая
useState и useReducer.
function CounterProvider({ children }) {
const [count, setCount] = useState(0);
const increment = () => setCount(count + 1);
return html`
<${CounterContext.Provider} .value=${{ count, increment }}>
${children}
<//>
`;
}
function CounterDisplay() {
const { count, increment } = useContext(CounterContext);
return html`
<div>
Счётчик: ${count}
<button @click=${increment}>+</button>
</div>
`;
}
Ключевой момент: при любом обновлении
count все компоненты, использующие этот контекст,
автоматически перерисуются.
light/dark) и функции
переключения, а дочерние компоненты используют useContext
для применения стилей.useReducer может заменить простую версию Redux,
предоставляя централизованное состояние для приложения.Провайдер контекста в Haunted становится центральным инструментом для управления состоянием и логикой на уровне компонентов, обеспечивая чистоту кода и реактивность без избыточной передачи свойств.