useState для управления состоянием

useState — это один из ключевых хуков Preact, предназначенный для управления состоянием функциональных компонентов. Он позволяет компоненту хранить данные, которые могут изменяться с течением времени, и автоматически перерисовывать интерфейс при этих изменениях.

Синтаксис хука:

import { useState } from 'preact/hooks';

const [state, setState] = useState(initialValue);
  • state — текущее значение состояния.
  • setState — функция для обновления состояния.
  • initialValue — начальное значение состояния, которое может быть любого типа: число, строка, объект, массив и т.д.

При изменении состояния через setState Preact выполняет эффективный ререндер только того компонента, где было вызвано обновление, минимизируя переработку DOM.


Пример использования useState

import { h } from 'preact';
import { useState } from 'preact/hooks';

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

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

    return (
        <div>
            <h1>Счётчик: {count}</h1>
            <button onCl ick={increment}>Увеличить</button>
            <button onCl ick={decrement}>Уменьшить</button>
        </div>
    );
}

В этом примере:

  • Инициализация состояния происходит через useState(0).
  • Обновление состояния через setCount вызывает ререндер компонента.
  • JSX автоматически отображает новое значение счётчика.

Состояние как объект

Состояние может быть объектом, что удобно для хранения нескольких значений в одном хранилище. При этом важно помнить, что setState не объединяет объекты автоматически, как в React классовых компонентах, а полностью заменяет старое состояние новым.

const [form, setForm] = useState({ name: '', email: '' });

const updateName = (e) => setForm({ ...form, name: e.target.value });
const updateEmail = (e) => setForm({ ...form, email: e.target.value });

Использование оператора spread (...) гарантирует сохранение остальных полей объекта при обновлении отдельного свойства.


Ленивое начальное состояние

useState поддерживает ленивую инициализацию. Вместо прямого значения можно передать функцию, которая вернёт начальное состояние. Это полезно, если вычисление начального значения ресурсоёмкое.

const [value, setValue] = useState(() => {
    console.log('Вычисляем начальное значение один раз');
    return Math.random();
});

Функция вызывается только при первой отрисовке компонента.


Обновления состояния на основе предыдущего значения

Для корректной работы с асинхронными обновлениями состояния рекомендуется использовать форму setState, где передаётся функция, принимающая текущее состояние:

const [count, setCount] = useState(0);

const increment = () => setCount(prev => prev + 1);

Это особенно важно при множественных последовательных вызовах setState, чтобы избежать рассинхронизации данных.


Состояние массивов

Для управления массивами также используется принцип неизменяемости:

const [items, setItems] = useState([]);

const addItem = (item) => setItems([...items, item]);
const removeItem = (index) => setItems(items.filter((_, i) => i !== index));
  • Новые элементы добавляются через spread или методы, возвращающие новый массив.
  • Фильтрация позволяет удалить элемент, не изменяя исходный массив.

Советы по оптимизации

  1. Минимизировать количество состояний: хранить только данные, которые реально влияют на рендер.
  2. Использовать объекты или массивы для связанных данных: уменьшает количество вызовов useState.
  3. Ленивая инициализация для сложных вычислений: экономит ресурсы при первой отрисовке.
  4. Функциональная форма setState: предотвращает ошибки при быстром последовательном обновлении состояния.

useState является фундаментальным инструментом для построения интерактивных компонентов в Preact. Он обеспечивает простое, но мощное управление состоянием, поддерживает объекты, массивы и позволяет писать чистый и предсказуемый код, оптимизированный под ререндеринг.