Haunted — это легковесная библиотека для создания веб-компонентов с использованием реактивных хуков в стиле React. Одной из мощнейших возможностей является параметризация хуков, которая позволяет создавать переиспользуемую логику с настройкой через аргументы, повышая модульность и удобство тестирования.
Хуки в Haunted представляют собой функции, которые управляют состоянием, побочными эффектами или вычисляемыми значениями компонента. Параметризация достигается за счёт передачи аргументов в сам хук:
import { useState, useEffect } from 'haunted';
function useCounter(initialValue = 0, step = 1) {
const [count, setCount] = useState(initialValue);
function increment() {
setCount(c => c + step);
}
return [count, increment];
}
Здесь useCounter принимает два параметра:
initialValue и step. Такой подход позволяет
использовать один и тот же хук с разными начальными значениями и шагом
изменения:
const [counter1, increment1] = useCounter(0, 1);
const [counter2, increment2] = useCounter(10, 5);
Важно понимать, что в Haunted аргументы хуков не являются
реактивными сами по себе. Если значение аргумента изменится
после первого вызова хука, его внутреннее состояние не обновится
автоматически. Для управления изменяемыми параметрами используется
комбинация useState и useEffect:
function useDynamicCounter(initialValue) {
const [count, setCount] = useState(initialValue);
useEffect(() => {
setCount(initialValue);
}, [initialValue]);
function increment() {
setCount(c => c + 1);
}
return [count, increment];
}
В этом примере счётчик будет подстраиваться под новые
значения параметра initialValue после его
изменения.
useEffect в Haunted может принимать зависимости,
аналогично React, что позволяет параметризовать побочные эффекты. Это
полезно для вызова API или подписок с разными конфигурациями:
function useFetch(url) {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
if (!url) return;
setLoading(true);
fetch(url)
.then(res => res.json())
.then(json => setData(json))
.finally(() => setLoading(false));
}, [url]);
return { data, loading };
}
Параметр url позволяет динамически менять источник
данных. Каждый новый URL триггерит повторное выполнение эффекта.
Для более сложной логики удобно использовать замыкания внутри хуков. Это позволяет хранить конфигурацию и поведение, переданное при создании хука:
function useTimer(interval = 1000) {
const [seconds, setSeconds] = useState(0);
useEffect(() => {
const id = setInterval(() => {
setSeconds(s => s + 1);
}, interval);
return () => clearInterval(id);
}, [interval]);
return seconds;
}
Параметр interval задаёт частоту обновления таймера.
Замыкание обеспечивает доступ к текущему значению интервала без
нарушения реактивности.
Хуки можно параметризовать не только примитивными типами, но и
объектами, функциями, массивами. Важно учитывать референсное
сравнение для зависимостей useEffect:
function useFilteredList(items, filterFn) {
const [filtered, setFiltered] = useState(() => items.filter(filterFn));
useEffect(() => {
setFiltered(items.filter(filterFn));
}, [items, filterFn]);
return filtered;
}
Если filterFn создаётся заново при каждом рендере,
эффект будет выполняться чаще, чем нужно. Решением является мемоизация
функций через useCallback или внешнее определение
функции.
Параметризация позволяет строить сложные композиции хуков, передавая одни и те же аргументы нескольким слоям логики:
function usePaginatedFetch(url, pageSize = 10) {
const [page, setPage] = useState(1);
const { data, loading } = useFetch(`${url}?_limit=${pageSize}&_page=${page}`);
function nextPage() {
setPage(p => p + 1);
}
function prevPage() {
setPage(p => Math.max(1, p - 1));
}
return { data, loading, page, nextPage, prevPage };
}
Здесь pageSize параметризует как сам хук
usePaginatedFetch, так и вложенный useFetch,
обеспечивая гибкость и переиспользуемость.
useEffect или useState, если их изменения
должны отражаться на состоянии.Параметризация хуков в Haunted превращает их в мощный инструмент для создания настраиваемой, реактивной и модульной логики веб-компонентов, позволяя строить гибкие и легко сопровождаемые приложения.