Haunted — это библиотека для создания веб-компонентов на основе Hooks, вдохновленных React, но с минимальным весом и прямой интеграцией с Custom Elements. Одной из ключевых задач при разработке сложных компонентов является отслеживание и логирование состояния. Это позволяет понимать, как и когда изменяются данные внутри компонента, и упрощает отладку.
Состояние в 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. Этот хук
позволяет реагировать на изменения состояния и выполнять побочные
действия, такие как вывод в консоль:
import { useEffect } from 'haunted';
function Counter() {
const [count, setCount] = useState(0);
useEffect(() => {
console.log('Состояние count изменилось:', count);
}, [count]);
return html`
<div>
<p>Счётчик: ${count}</p>
<button @click=${() => setCount(count + 1)}>Увеличить</button>
</div>
`;
}
customElements.define('my-counter', component(Counter));
useEffect принимает два аргумента: функцию-эффект и
массив зависимостей. Функция выполняется каждый раз, когда хотя бы одно
значение из массива зависимостей изменяется.
Для крупных проектов удобно создать обёртку для логирования состояния, которая автоматически будет отслеживать все изменения.
function useLoggedState(initialValue, name = 'state') {
const [value, setValue] = useState(initialValue);
useEffect(() => {
console.log(`[LOG] ${name}:`, value);
}, [value]);
return [value, setValue];
}
Теперь можно использовать useLoggedState вместо
useState, чтобы получать автоматическое логирование:
function Counter() {
const [count, setCount] = useLoggedState(0, 'count');
return html`
<div>
<p>Счётчик: ${count}</p>
<button @click=${() => setCount(count + 1)}>Увеличить</button>
</div>
`;
}
customElements.define('my-counter', component(Counter));
Если состояние представляет собой объект или массив, важно логировать копию состояния, чтобы избежать путаницы с мутациями:
function useLoggedObjectState(initialValue, name = 'state') {
const [state, setState] = useState(initialValue);
useEffect(() => {
console.log(`[LOG] ${name}:`, JSON.parse(JSON.stringify(state)));
}, [state]);
return [state, setState];
}
Пример использования:
function TodoList() {
const [todos, setTodos] = useLoggedObjectState([], 'todos');
const addTodo = (text) => setTodos([...todos, { text, done: false }]);
return html`
<div>
<ul>
${todos.map(todo => html`<li>${todo.text}</li>`)}
</ul>
<button @click=${() => addTodo('Новое задание')}>Добавить</button>
</div>
`;
}
customElements.define('my-todo', component(TodoList));
Для крупных приложений логирование в консоль может быть недостаточно.
Haunted позволяет интегрироваться с любыми системами логирования,
например loglevel или собственными сервисами:
import log from 'loglevel';
function useLoggedStateExternal(initialValue, name = 'state') {
const [value, setValue] = useState(initialValue);
useEffect(() => {
log.info(`[LOG] ${name}:`, value);
}, [value]);
return [value, setValue];
}
Такой подход позволяет централизовать сбор информации о состоянии компонентов, хранить логи на сервере или интегрировать с аналитикой.
useEffect с зависимостями, чтобы фиксировать только
изменения.Эти техники позволяют создать прозрачное и контролируемое управление состоянием компонентов Haunted, ускоряют отладку и повышают надежность интерфейсов.