Отличия от useEffect

Библиотека Haunted предлагает подход к созданию веб-компонентов, основанный на функциональных реактивных хуках, аналогичных React, но с важными отличиями в жизненном цикле и управлении состоянием. Основной элемент — хуки Haunted, такие как useState, useEffect, useReducer и другие, реализованные для нативных веб-компонентов.


Жизненный цикл и useEffect

В React useEffect используется для побочных эффектов после рендера компонента. Основные особенности:

  • Выполняется после каждого рендера, если зависимости изменились.
  • Может возвращать функцию для очистки эффекта.
  • Зависит от массива зависимостей, который указывает, когда эффект должен срабатывать.

В Haunted useEffect имеет схожую концепцию, но с ключевыми отличиями:

  1. Привязка к веб-компоненту Эффекты в Haunted привязаны к жизненному циклу нативного элемента. Они срабатывают после первого рендера элемента и повторяются при изменении зависимостей. Однако уничтожение компонента автоматически вызывает функции очистки, что делает управление ресурсами более прозрачным для веб-компонентов.

  2. Поддержка повторного рендера через хуки В Haunted компонент может ререндериться внутри функции-хука, без необходимости создавать отдельные классы. useEffect учитывает изменения состояния, возвращаемого useState или useReducer, и срабатывает аналогично React, но напрямую внутри элемента DOM.

  3. Отсутствие виртуального DOM Haunted не использует виртуальный DOM. Следовательно, useEffect в Haunted реагирует на реальные изменения DOM. Это означает, что операции с DOM в эффектах выполняются сразу на элементе, без дополнительного этапа согласования, как в React.


Управление очисткой эффектов

В Haunted очистка эффектов работает следующим образом:

  • Функция, возвращаемая из useEffect, вызывается при удалении элемента из DOM или перед повторным вызовом эффекта, если зависимости изменились.
  • Это обеспечивает корректное освобождение ресурсов, аналогично React, но в контексте нативных элементов, что важно для сторонних библиотек или событий.

Пример:

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, но есть нюанс:

  • Массив зависимостей отслеживает только изменения значений, переданных в него напрямую.
  • Изменения вложенных объектов не отслеживаются автоматически, как и в React, поэтому для сложных объектов нужно использовать отдельное состояние через useState или useReducer.

Отличия в синтаксисе и семантике

  • В Haunted эффект всегда привязан к компоненту, а не к дереву компонентов.
  • Нет необходимости создавать отдельные классы с методами connectedCallback и disconnectedCallbackuseEffect полностью управляет жизненным циклом.
  • Можно комбинировать несколько эффектов в одном компоненте, и каждый эффект будет работать независимо, что упрощает модульность кода.

Пример с несколькими эффектами:

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>`;
}

Каждый эффект изолирован, и их очистка выполняется независимо, что повышает надежность управления ресурсами.


Интеграция с DOM

  • В Haunted 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>`;
}

Резюме ключевых отличий

  1. Haunted не использует виртуальный DOM, эффекты работают напрямую с DOM.
  2. useEffect привязан к жизненному циклу нативного элемента, а не всего дерева компонентов.
  3. Автоматическая очистка эффектов при удалении элемента.
  4. Возможность создавать компоненты полностью функционально без классов.
  5. Массив зависимостей работает аналогично React, но стоит учитывать особенности отслеживания объектов.

Эти отличия делают Haunted удобным инструментом для реактивного управления состоянием и побочными эффектами в независимых веб-компонентах, сочетая простоту React-хуков с нативной интеграцией в DOM.