Haunted — это библиотека для создания веб-компонентов на базе функций, вдохновленных React Hooks, с полной поддержкой реактивного состояния. Одним из ключевых аспектов эффективного использования Haunted является правильная организация и синхронизация состояния компонентов. Этот процесс включает управление локальным состоянием, передачу данных между компонентами и реакцию на внешние изменения.
В Haunted локальное состояние определяется с помощью хука
useState. Этот хук возвращает текущее значение состояния и
функцию для его обновления. Обновление состояния автоматически
инициирует повторный рендер компонента.
import { html, component, useState } from 'haunted';
function Counter() {
const [count, setCount] = useState(0);
return html`
<div>
<p>Счётчик: ${count}</p>
<button @click=${() => setCount(count + 1)}>Увеличить</button>
</div>
`;
}
customElements.define('my-counter', component(Counter));
Особенности локального состояния:
useState может принимать как примитивные значения, так
и объекты. При работе с объектами необходимо создавать новые копии для
корректной работы рендеринга.useEffectДля синхронизации состояния с побочными эффектами используется
useEffect. Этот хук позволяет реагировать на изменения
зависимостей и выполнять действия, например, обновление DOM, запросы к
API или таймеры.
import { html, component, useState, useEffect } from 'haunted';
function Timer() {
const [seconds, setSeconds] = useState(0);
useEffect(() => {
const interval = setInterval(() => setSeconds(s => s + 1), 1000);
return () => clearInterval(interval);
}, []);
return html`<p>Прошло секунд: ${seconds}</p>`;
}
customElements.define('my-timer', component(Timer));
Ключевые моменты:
useEffect выполняется после рендера, что предотвращает
блокировку UI.[] означает
однократный вызов при монтировании.Haunted поддерживает организацию состояния на более высоком уровне с помощью кастомных хуков и реактивных объектов. Для сложных компонентов рекомендуется создавать собственные хуки для управления логикой и синхронизации между компонентами.
import { useState, useEffect } from 'haunted';
function useFetch(url) {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
fetch(url)
.then(res => res.json())
.then(json => {
setData(json);
setLoading(false);
});
}, [url]);
return [data, loading];
}
Использование кастомных хуков:
import { html, component } from 'haunted';
import { useFetch } from './hooks.js';
function DataViewer({ url }) {
const [data, loading] = useFetch(url);
return html`
${loading ? html`<p>Загрузка...</p>` : html`<pre>${JSON.stringify(data, null, 2)}</pre>`}
`;
}
customElements.define('data-viewer', component(DataViewer));
Преимущества:
Состояние компонентов можно синхронизировать с их свойствами
(props). Свойства — это внешний способ передавать данные
компоненту, а useState позволяет реагировать на их
изменения.
import { html, component, useState, useEffect } from 'haunted';
function Greeting({ name }) {
const [displayName, setDisplayName] = useState(name);
useEffect(() => {
setDisplayName(name);
}, [name]);
return html`<p>Привет, ${displayName}!</p>`;
}
customElements.define('my-greeting', component(Greeting));
Особенности синхронизации с props:
useEffect для отслеживания изменений
свойств.Для синхронизации состояния между множеством компонентов можно
использовать паттерн глобального состояния через контексты. Haunted не
имеет встроенного контекста, но его можно реализовать через кастомные
события или сторонние библиотеки, например, lit или
redux.
Пример через кастомное событие:
// Эмиттер состояния
const state = { count: 0 };
function increment() {
state.count++;
window.dispatchEvent(new CustomEvent('state-change', { detail: state.count }));
}
// Подписка в компоненте
function Counter() {
const [count, setCount] = useState(state.count);
useEffect(() => {
const handler = (e) => setCount(e.detail);
window.addEventListener('state-change', handler);
return () => window.removeEventListener('state-change', handler);
}, []);
return html`<button @click=${increment}>Счёт: ${count}</button>`;
}
customElements.define('global-counter', component(Counter));
Выводы по глобальному состоянию:
useState для локальных значений и
useEffect для их синхронизации с внешними источниками.Синхронизация состояния в Haunted обеспечивает реактивность и предсказуемость поведения компонентов, делая архитектуру приложения более чистой и модульной.