Создание собственных hooks

Bliss.js предоставляет разработчику мощный механизм реактивности через hooks, позволяющий управлять состоянием, эффектами и жизненным циклом компонентов. Хотя библиотека включает ряд стандартных hooks, создание собственных расширяет возможности реактивной архитектуры и упрощает повторное использование логики.

Основы кастомных hooks

Кастомный hook — это функция, имя которой начинается с use и которая может вызывать другие hooks внутри себя. Они не являются компонентами, но позволяют инкапсулировать поведение и состояние.

Пример базового пользовательского hook:

import { useState, useEffect } from 'bliss';

function useCounter(initialValue = 0) {
    const [count, setCount] = useState(initialValue);

    const increment = () => setCount(count + 1);
    const decrement = () => setCount(count - 1);

    return { count, increment, decrement };
}

В этом примере useCounter инкапсулирует управление числовым состоянием и предоставляет интерфейс для увеличения и уменьшения значения. Любой компонент может использовать его так:

function CounterComponent() {
    const { count, increment, decrement } = useCounter(10);

    return (
        <div>
            <p>Счетчик: {count}</p>
            <button oncl ick={increment}>+</button>
            <button oncl ick={decrement}>-</button>
        </div>
    );
}

Взаимодействие с эффектами

Hooks в Bliss.js поддерживают эффекты, которые позволяют реагировать на изменения состояния или пропсов. Эффекты создаются с помощью useEffect внутри кастомного hook:

import { useState, useEffect } from 'bliss';

function useWindowWidth() {
    const [width, setWidth] = useState(window.innerWidth);

    useEffect(() => {
        const handleResize = () => setWidth(window.innerWidth);
        window.addEventListener('resize', handleResize);

        return () => window.removeEventListener('resize', handleResize);
    }, []);

    return width;
}

Здесь useWindowWidth отслеживает ширину окна и обновляет состояние при изменении размера. useEffect гарантирует корректное добавление и удаление обработчика.

Параметризация кастомных hooks

Hooks можно делать параметризованными, чтобы они адаптировались к различным сценариям:

function useLocalStorage(key, initialValue) {
    const [value, setValue] = useState(() => {
        const stored = localStorage.getItem(key);
        return stored !== null ? JSON.parse(stored) : initialValue;
    });

    useEffect(() => {
        localStorage.setItem(key, JSON.stringify(value));
    }, [key, value]);

    return [value, setValue];
}

Такой hook можно использовать для любого ключа и начального значения, создавая реактивное хранилище в локальном хранилище браузера.

Комбинирование hooks

Bliss.js позволяет комбинировать несколько hooks внутри одного кастомного. Это полезно для создания сложной логики без дублирования кода:

function useResponsiveCounter(initialValue = 0) {
    const width = useWindowWidth();
    const { count, increment, decrement } = useCounter(initialValue);

    useEffect(() => {
        if (width < 500) {
            console.log('Маленький экран, уменьшение счетчика на 1');
            decrement();
        }
    }, [width]);

    return { count, increment, decrement, width };
}

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

Рекомендации по созданию собственных hooks

  1. Соблюдать правила hooks: вызывать их только в теле функции hook или компонента, не внутри условных операторов или циклов.
  2. Инкапсулировать логику: hook должен выполнять одну конкретную задачу и возвращать только необходимые данные и методы.
  3. Использовать эффект только при необходимости: избегать лишних подписок и пересчетов.
  4. Параметризовать для гибкости: передавать параметры вместо жесткой привязки к конкретным значениям или элементам.
  5. Возвращать минимальный интерфейс: включать только то, что реально нужно внешнему компоненту.

Практика повторного использования

Создание собственных hooks позволяет стандартизировать подходы к управлению состоянием и эффектами. В больших приложениях можно собрать библиотеку hooks, которая упрощает разработку новых компонентов, уменьшает дублирование кода и повышает читаемость.

function useAuth() {
    const [user, setUser] = useState(null);

    const login = async (credentials) => {
        const response = await fetch('/login', { method: 'POST', body: JSON.stringify(credentials) });
        const data = await response.json();
        setUser(data.user);
    };

    const logout = () => setUser(null);

    return { user, login, logout };
}

Такой hook инкапсулирует авторизацию, позволяя любому компоненту подключаться к состоянию пользователя без повторного написания логики запросов и обработки ответа.

Интеграция с компонентами

Кастомные hooks тесно интегрируются с компонентами Bliss.js, поддерживая реактивный рендер при изменении состояния. Это делает архитектуру более модульной, а код — предсказуемым.

Hooks можно использовать как для UI-логики, так и для работы с внешними API, хранилищем данных, подписками на события и анимациями, обеспечивая единый подход к управлению состоянием и эффектами.