useContext в Atomico является инструментом для передачи
данных между компонентами без необходимости пробрасывать пропсы через
каждый уровень иерархии. Он создаёт контекст, позволяющий дочерним
компонентам получать доступ к данным, объявленным на более высоком
уровне, обеспечивая удобный и чистый способ управления состоянием
приложения.
Для создания контекста используется функция
createContext из Atomico:
import { createContext, useContext, useState, html } from "atomico";
const ThemeContext = createContext();
createContext возвращает объект с двумя ключевыми
свойствами: Provider и Consumer. В Atomico
чаще используется Provider в сочетании с хуком
useContext.
Пример использования Provider:
function App() {
const [theme, setTheme] = useState("light");
return html`
<${ThemeContext.Provider} value=${{ theme, setTheme }}>
<${Toolbar} />
<//>
`;
}
Здесь value задаёт данные, доступные для всех дочерних
компонентов. Любой компонент внутри
<ThemeContext.Provider> сможет получить доступ к
theme и setTheme.
Дочерние компоненты используют useContext для доступа к
данным:
function Toolbar() {
const { theme, setTheme } = useContext(ThemeContext);
return html`
<div>
<p>Текущая тема: ${theme}</p>
<button onCl ick=${() => setTheme(theme === "light" ? "dark" : "light")}>
Переключить тему
</button>
</div>
`;
}
Ключевые моменты:
useContext возвращает значение из ближайшего
родительского Provider данного контекста.value Provider автоматически
вызывают повторный рендер всех компонентов, использующих
useContext.Контекст поддерживает динамическое изменение значений. При обновлении
состояния в родительском компоненте все дочерние компоненты,
использующие useContext, обновятся:
function App() {
const [theme, setTheme] = useState("light");
const toggleTheme = () => setTheme(theme === "light" ? "dark" : "light");
return html`
<${ThemeContext.Provider} value=${{ theme, toggleTheme }}>
<${Toolbar} />
<${Content} />
<//>
`;
}
function Content() {
const { theme } = useContext(ThemeContext);
return html`<div style=${`background: ${theme === "light" ? "#fff" : "#333"}; color: ${theme === "light" ? "#000" : "#fff"}`}>
Контент с темой ${theme}
</div>`;
}
Любая функция, переданная через value, может
использоваться для управления состоянием контекста, что делает
useContext гибким инструментом для глобального состояния
без сторонних библиотек.
Atomico позволяет использовать несколько контекстов одновременно. Для
этого создаются несколько createContext и используются
соответствующие Provider:
const UserContext = createContext();
const SettingsContext = createContext();
function App() {
const [user, setUser] = useState({ name: "Alex" });
const [settings, setSettings] = useState({ notifications: true });
return html`
<${UserContext.Provider} value=${{ user, setUser }}>
<${SettingsContext.Provider} value=${{ settings, setSettings }}>
<${Dashboard} />
<//>
<//>
`;
}
Компоненты внутри Dashboard могут подключаться к каждому
контексту независимо:
function Dashboard() {
const { user } = useContext(UserContext);
const { settings, setSettings } = useContext(SettingsContext);
return html`
<div>
<p>Пользователь: ${user.name}</p>
<button onCl ick=${() => setSettings({ ...settings, notifications: !settings.notifications })}>
Переключить уведомления
</button>
</div>
`;
}
Использование контекста может вызвать лишние перерисовки, если объект
value создаётся заново при каждом рендере. Рекомендуется
мемоизировать значения с помощью useMemo:
import { useMemo } from "atomico";
function App() {
const [theme, setTheme] = useState("light");
const contextValue = useMemo(() => ({ theme, setTheme }), [theme]);
return html`
<${ThemeContext.Provider} value=${contextValue}>
<${Toolbar} />
<//>
`;
}
Это уменьшает количество ненужных обновлений и повышает производительность при сложных и крупных приложениях.
В отличие от простого состояния, контекст позволяет передавать функции, методы и любые объекты. Это особенно удобно для управления действиями, которые должны быть доступны во многих местах приложения:
const ModalContext = createContext();
function App() {
const [isOpen, setIsOpen] = useState(false);
const openModal = () => setIsOpen(true);
const closeModal = () => setIsOpen(false);
return html`
<${ModalContext.Provider} value=${{ isOpen, openModal, closeModal }}>
<${Header} />
<${Main} />
<${Modal} />
<//>
`;
}
Дочерние компоненты могут использовать openModal и
closeModal без прямого проброса через пропсы.
createContext и Provider.value помогает избежать лишних
перерисовок.Эффективное использование useContext в Atomico позволяет
создавать чистую архитектуру компонентов, минимизировать вложенность
пропсов и централизовать управление состоянием приложения.