Концепция компонентов и их классификация

Компоненты как основа архитектуры

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

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

Функциональные и классовые компоненты

Preact поддерживает два типа компонентов: функциональные и классовые.

Функциональные компоненты представляют собой обычные JavaScript-функции, которые принимают объект props и возвращают JSX:

import { h } from 'preact';

function Button({ label, onClick }) {
    return <button onCl ick={onClick}>{label}</button>;
}

Функциональные компоненты лёгкие и простые в использовании. В Preact 10+ они полностью поддерживают хуки, что позволяет управлять состоянием и побочными эффектами без использования классов.

Классовые компоненты создаются через наследование от Preact.Component. Они позволяют использовать методы жизненного цикла и управлять локальным состоянием через this.state:

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 <button onCl ick={this.increment}>{this.state.count}</button>;
    }
}

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

Пропсы и состояние

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

function Greeting({ name }) {
    return <h1>Привет, {name}!</h1>;
}

Состояние (state) — это данные, управляемые самим компонентом. Изменение состояния инициирует повторный рендер компонента, что позволяет динамически обновлять интерфейс:

import { useState } from 'preact/hooks';

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

    return <button onCl ick={() => setCount(count + 1)}>{count}</button>;
}

Хуки useState, useEffect и другие предоставляют мощные средства управления состоянием и побочными эффектами в функциональных компонентах.

Классификация компонентов по назначению

Компоненты можно классифицировать по различным признакам:

  1. Контейнерные и презентационные

    • Контейнерные компоненты отвечают за логику, работу с данными и состояние. Они редко содержат чисто визуальный код.
    • Презентационные компоненты фокусируются на отображении данных и получении props. Они не управляют состоянием и могут быть полностью переиспользуемыми.
  2. Контролируемые и неконтролируемые

    • Контролируемые компоненты получают своё состояние извне через props и уведомляют об изменениях через callback-функции.
    • Неконтролируемые компоненты сами управляют своим состоянием, предоставляя минимальный внешний контроль.
  3. Состоящие и обобщённые (Higher-Order Components)

    • Состоящие компоненты (composite) строятся из нескольких вложенных компонентов, формируя сложные UI-блоки.
    • Обобщённые компоненты (HOC) — это функции, которые принимают компонент и возвращают новый, расширяя его функциональность без изменения исходного кода.

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

Классовые компоненты обладают набором методов жизненного цикла:

  • constructor — инициализация состояния и привязка методов.
  • componentDidMount — вызов после первого рендера, полезен для работы с API или сторонними библиотеками.
  • componentDidUpdate — вызывается после обновления props или state.
  • componentWillUnmount — очистка ресурсов перед удалением компонента.

Функциональные компоненты используют хуки useEffect для имитации методов жизненного цикла:

import { useEffect } from 'preact/hooks';

function Timer() {
    useEffect(() => {
        const interval = setInterval(() => console.log('tick'), 1000);
        return () => clearInterval(interval);
    }, []);

    return <div>Таймер запущен</div>;
}

Рендеринг и виртуальный DOM

Preact использует виртуальный DOM для оптимизации обновлений. Каждый компонент возвращает описание UI, которое сравнивается с предыдущим состоянием, и минимальные изменения применяются к реальному DOM. Это повышает производительность и снижает нагрузку на браузер.

Компоненты могут быть одноразовыми (stateless) или динамическими (stateful), что напрямую влияет на частоту их повторного рендера.

Вывод

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