Библиотека Haunted предлагает подход к созданию
веб-компонентов, основанный на функциональных реактивных хуках,
аналогичных React, но с важными отличиями в жизненном цикле и управлении
состоянием. Основной элемент — хуки Haunted, такие как
useState, useEffect, useReducer и
другие, реализованные для нативных веб-компонентов.
useEffectВ React useEffect используется для побочных эффектов
после рендера компонента. Основные особенности:
В Haunted useEffect имеет схожую концепцию, но с
ключевыми отличиями:
Привязка к веб-компоненту Эффекты в Haunted привязаны к жизненному циклу нативного элемента. Они срабатывают после первого рендера элемента и повторяются при изменении зависимостей. Однако уничтожение компонента автоматически вызывает функции очистки, что делает управление ресурсами более прозрачным для веб-компонентов.
Поддержка повторного рендера через хуки В
Haunted компонент может ререндериться внутри
функции-хука, без необходимости создавать отдельные классы.
useEffect учитывает изменения состояния, возвращаемого
useState или useReducer, и срабатывает
аналогично React, но напрямую внутри элемента DOM.
Отсутствие виртуального DOM Haunted не
использует виртуальный DOM. Следовательно, useEffect в
Haunted реагирует на реальные изменения DOM. Это означает, что операции
с DOM в эффектах выполняются сразу на элементе, без дополнительного
этапа согласования, как в React.
В Haunted очистка эффектов работает следующим образом:
useEffect, вызывается
при удалении элемента из DOM или перед повторным
вызовом эффекта, если зависимости изменились.Пример:
import { html, component, useEffect, useState } from 'haunted';
function Timer() {
const [count, setCount] = useState(0);
useEffect(() => {
const interval = setInterval(() => setCount(c => c + 1), 1000);
return () => clearInterval(interval);
}, []);
return html`<p>Счетчик: ${count}</p>`;
}
customElements.define('x-timer', component(Timer));
Здесь эффект запускается один раз при монтировании компонента, а при
удалении <x-timer> автоматически вызывается функция
очистки.
В Haunted зависимости useEffect работают почти идентично
React, но есть нюанс:
useState или
useReducer.connectedCallback и disconnectedCallback —
useEffect полностью управляет жизненным циклом.Пример с несколькими эффектами:
function MultiEffect() {
const [name, setName] = useState('Haunted');
const [count, setCount] = useState(0);
useEffect(() => {
console.log('Имя изменилось:', name);
}, [name]);
useEffect(() => {
const timer = setInterval(() => setCount(c => c + 1), 1000);
return () => clearInterval(timer);
}, []);
return html`<p>${name}: ${count}</p>`;
}
Каждый эффект изолирован, и их очистка выполняется независимо, что повышает надежность управления ресурсами.
useEffect идеально подходит для работы с
реальными DOM-событиями, например
addEventListener на элементе.function ClickTracker() {
const [clicks, setClicks] = useState(0);
useEffect(() => {
const handler = () => setClicks(c => c + 1);
window.addEventListener('click', handler);
return () => window.removeEventListener('click', handler);
}, []);
return html`<p>Клики: ${clicks}</p>`;
}
useEffect привязан к жизненному циклу нативного
элемента, а не всего дерева компонентов.Эти отличия делают Haunted удобным инструментом для реактивного управления состоянием и побочными эффектами в независимых веб-компонентах, сочетая простоту React-хуков с нативной интеграцией в DOM.