Preact как основа компонентов

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

Компоненты в Preact

Компонент в Preact — это функция или класс, который возвращает JSX. Функциональные компоненты являются предпочтительными, поскольку они проще, короче и легче поддерживаются.

import { h } from 'preact';

function Button({ label, onClick }) {
    return <button onCl ick={onClick}>{label}</button>;
}
  • h — это функция гиперэлементов, аналог JSX в Preact.
  • Свойства компонента (props) передаются как аргументы функции.
  • JSX транспилируется в вызовы h(), создавая виртуальный DOM.

Классовые компоненты реже используются, но также поддерживаются для сложных сценариев с состоянием и методами жизненного цикла.

import { h, Component } from 'preact';

class Counter extends Component {
    constructor(props) {
        super(props);
        this.state = { count: 0 };
    }

    increment = () => {
        this.setState({ count: this.state.count + 1 });
    };

    render() {
        return (
            <div>
                <p>{this.state.count}</p>
                <button onCl ick={this.increment}>Увеличить</button>
            </div>
        );
    }
}

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

Props — неизменяемые данные, передаваемые компоненту извне. Они обеспечивают одностороннюю связь данных, делая компонент предсказуемым и легко тестируемым.

State — локальное состояние компонента. В функциональных компонентах управляется через хук useState:

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

function Toggle() {
    const [on, setOn] = useState(false);

    return (
        <button onCl ick={() => setOn(!on)}>
            {on ? 'Вкл' : 'Выкл'}
        </button>
    );
}
  • Каждый вызов useState возвращает массив с текущим значением состояния и функцией для его изменения.
  • Изменение состояния вызывает повторный рендер компонента, обновляя DOM только там, где это необходимо.

Жизненный цикл компонентов

Preact поддерживает методы жизненного цикла для классовых компонентов:

  • componentDidMount — вызывается после первого рендера.
  • componentDidUpdate — вызывается после обновления пропсов или состояния.
  • componentWillUnmount — вызывается перед удалением компонента.

В функциональных компонентах аналогичные действия выполняются через хук useEffect:

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

function Timer() {
    const [seconds, setSeconds] = useState(0);

    useEffect(() => {
        const interval = setInterval(() => setSeconds(s => s + 1), 1000);
        return () => clearInterval(interval); // очистка при удалении компонента
    }, []);

    return <p>Прошло секунд: {seconds}</p>;
}
  • Второй аргумент useEffect позволяет контролировать, когда эффект должен выполняться.
  • Пустой массив [] означает, что эффект выполнится только один раз после монтирования компонента.

События и обработчики

Preact использует синтетические события, совместимые с React. События привязываются через JSX:

<button onCl ick={() => console.log('Клик!')}>Кликни меня</button>

Особенности работы:

  • События именуются в camelCase (onClick, onInput).
  • Передаваемые функции должны быть ссылками на обработчики, а не результатами их вызова.

Контекст

Контекст позволяет передавать данные глубоко в дерево компонентов, минуя цепочку props. В Preact используется createContext и useContext:

import { h } from 'preact';
import { createContext } from 'preact';
import { useContext } from 'preact/hooks';

const ThemeContext = createContext('light');

function ThemedButton() {
    const theme = useContext(ThemeContext);
    return <button className={theme}>Кнопка</button>;
}
  • createContext создаёт объект контекста с дефолтным значением.
  • Provider позволяет переопределять значение для дочерних компонентов.

Оптимизация рендеринга

Preact минимизирует количество обновлений DOM через виртуальный DOM. Основные приёмы оптимизации:

  • Использование ключей (key) при рендеринге списков для корректного сопоставления элементов.
  • Минимизация обновлений состояния.
  • Избегание создания новых функций внутри JSX при каждом рендере (лучше выносить обработчики за пределы рендера).
<ul>
    {items.map(item => <li key={item.id}>{item.name}</li>)}
</ul>
  • key должен быть уникальным и стабильным для каждого элемента списка.
  • Это позволяет Preact эффективно перерисовывать только изменённые элементы.

Заключение о подходе Preact

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