Декларативная подписка — это механизм, позволяющий компонентам Atomico автоматически реагировать на изменения данных или внешних источников, минимизируя ручное управление подписками и их отпиской. Она строится на принципах реактивности и удобна для интеграции с асинхронными потоками событий.
В Atomico декларативная подписка реализуется через функцию
useSubscription. Она принимает источник данных и возвращает
текущее состояние этого источника, автоматически обновляя компонент при
изменении данных.
import { component, useSubscription } from "atomico";
function Clock() {
const time = useSubscription(() => new Date(), 1000);
return <host>{time.toLocaleTimeString()}</host>;
}
export default component(Clock);
В этом примере useSubscription получает
функцию-источник, которая вызывается с интервалом в 1000 миллисекунд.
Компонент Clock автоматически перерисовывается при каждом
обновлении времени.
Ключевые моменты:
Atomico позволяет подключаться к промисам, событиям и любым объектам,
реализующим интерфейс EventTarget.
import { component, useSubscription } from "atomico";
function MouseTracker() {
const position = useSubscription((set) => {
const handler = (e) => set({ x: e.clientX, y: e.clientY });
window.addEventListener("mousemove", handler);
return () => window.removeEventListener("mousemove", handler);
}, { x: 0, y: 0 });
return <host>
X: {position.x}, Y: {position.y}
</host>;
}
export default component(MouseTracker);
Здесь подписка создаёт слушатель события mousemove и
автоматически отписывается при демонтировании компонента. Объект
set используется для обновления состояния подписки.
Особенности:
Подписка может отслеживать изменения зависимостей, аналогично хук
useEffect в React.
import { component, useSubscription, useProp } from "atomico";
function UserInfo() {
const userId = useProp("userId");
const user = useSubscription(
async (set) => {
const res = await fetch(`/api/user/${userId}`);
set(await res.json());
},
null,
[userId]
);
return <host>{user ? user.name : "Загрузка..."}</host>;
}
export default component(UserInfo);
useSubscription — массив
зависимостей.userId.Atomico позволяет комбинировать несколько подписок внутри одного компонента. Каждая подписка управляет своим состоянием и не мешает другим.
import { component, useSubscription } from "atomico";
function Dashboard() {
const time = useSubscription(() => new Date(), 1000);
const windowSize = useSubscription((set) => {
const handler = () => set({ width: window.innerWidth, height: window.innerHeight });
window.addEventListener("resize", handler);
return () => window.removeEventListener("resize", handler);
}, { width: window.innerWidth, height: window.innerHeight });
return <host>
Время: {time.toLocaleTimeString()}<br/>
Размер окна: {windowSize.width}x{windowSize.height}
</host>;
}
export default component(Dashboard);
Выводы по композиции:
Для оптимизации можно использовать мемоизацию источников. Это предотвращает лишние перерисовки при неизменных данных.
import { component, useSubscription, useMemo } from "atomico";
function Fibonacci({ n }) {
const fib = useMemo(() => {
const compute = (x) => (x <= 1 ? 1 : compute(x - 1) + compute(x - 2));
return compute(n);
}, [n]);
const value = useSubscription(() => fib, [fib]);
return <host>Fib({n}) = {value}</host>;
}
export default component(Fibonacci);
useMemo кэширует вычисление функции.fib.Декларативная подписка в Atomico обеспечивает чистый, реактивный и безопасный способ управления состоянием компонентов, особенно в динамических интерфейсах с множеством асинхронных источников.