Haunted — это библиотека для создания веб-компонентов с реактивным состоянием на основе Hooks, вдохновленных React. Основной упор сделан на лёгкость, минимальный синтаксис и интеграцию с нативными веб-компонентами. Ключевой концепт — состояние компонента, которое управляет его реактивным поведением и ререндером при изменении данных.
useStateФункция 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(initialValue) возвращает массив из двух
элементов: текущее значение состояния и функцию для его обновления.setCount) компонент
автоматически перерендеривается.Важная деталь: порядок вызовов useState
критически важен. Изменение порядка нарушит соответствие значений
состояний между рендерами.
Haunted использует шаблоны lit-html для генерации
DOM. Когда состояние изменяется через setState, библиотека
сравнивает предыдущий и новый результат шаблона, обновляя только
изменившиеся узлы. Такой подход минимизирует операции с DOM и повышает
производительность.
setCount(count + 1); // триггерит ререндер
Процесс рендера можно разделить на этапы:
html.Для хранения объектов или массивов важно не мутировать данные напрямую, а создавать новые копии. Это позволяет Haunted корректно отслеживать изменения.
const [items, setItems] = useState([]);
function addItem(newItem) {
setItems([...items, newItem]);
}
Пояснение: Если изменять массив через
push, Haunted не заметит изменения, и ререндер не
произойдет. Создание нового массива через spread-оператор гарантирует
реактивность.
Компонент может иметь несколько независимых состояний:
const [name, setName] = useState('Иван');
const [age, setAge] = useState(30);
Каждое состояние управляется отдельно. Обновление одного не затрагивает другие, что позволяет более тонко контролировать ререндеры и минимизировать ненужные обновления DOM.
Состояние в Haunted локально для компонента. Для обмена данными между компонентами используют:
this.dispatchEvent(new CustomEvent('update', { detail: count }));
События позволяют родительскому компоненту реагировать на изменения состояния дочернего компонента без прямого доступа к его внутренним данным.
Haunted управляет состоянием через hook-based lifecycle:
useEffect с возвращаемой
функцией:import { useEffect } from 'haunted';
useEffect(() => {
const id = setInterval(() => console.log('tick'), 1000);
return () => clearInterval(id);
}, []); // пустой массив — эффект срабатывает один раз при монтировании
Это позволяет управлять побочными эффектами в сочетании с состоянием, обеспечивая безопасное создание и очистку ресурсов.
Haunted не ограничивается простыми типами данных. Реактивность работает с объектами, массивами, функциями и другими структурами при соблюдении иммутабельного подхода:
const [user, setUser] = useState({ name: 'Иван', age: 30 });
setUser({ ...user, age: 31 });
Иммутабельность позволяет библиотеке точно определять, что изменилось, и обновлять только необходимые части DOM.
Haunted объединяет простоту веб-компонентов и мощь реактивного управления состоянием, создавая современный инструмент для построения динамичных интерфейсов на чистом JavaScript.