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

Функциональные компоненты в Stencil представляют собой упрощённый способ создания компонентов без использования классов. Они особенно полезны для компонентов, не требующих внутреннего состояния или сложной логики жизненного цикла.

Создание функционального компонента

Функциональный компонент объявляется как обычная функция JavaScript или TypeScript, которая возвращает JSX. Пример минимального компонента:

import { FunctionalComponent, h } from '@stencil/core';

interface MyComponentProps {
  name: string;
}

const MyComponent: FunctionalComponent<MyComponentProps> = ({ name }) => {
  return <div>Привет, {name}!</div>;
};

export default MyComponent;

Ключевые моменты:

  • FunctionalComponent — тип из @stencil/core, позволяющий задать пропсы компонента.
  • Пропсы передаются через объект аргументов функции.
  • JSX внутри функции преобразуется Stencil в DOM-элементы.

Использование пропсов

Пропсы функциональных компонентов работают аналогично классам. Типизация пропсов позволяет обеспечить строгую проверку и автодополнение в редакторах.

interface ButtonProps {
  label: string;
  disabled?: boolean;
}

const Button: FunctionalComponent<ButtonProps> = ({ label, disabled = false }) => {
  return (
    <button disabled={disabled}>
      {label}
    </button>
  );
};

Особенности:

  • Опциональные пропсы можно задавать через ? и дефолтные значения внутри функции.
  • Стандартные HTML-атрибуты можно использовать напрямую в JSX.

Состояние и хуки

Хотя функциональные компоненты не имеют классового состояния, Stencil предоставляет хуки, аналогичные React:

  • useState для управления локальным состоянием.
  • useEffect для отслеживания изменений пропсов или состояния.
  • useContext для доступа к контексту.

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

import { h, FunctionalComponent, useState } from '@stencil/core';

const Counter: FunctionalComponent = () => {
  const [count, setCount] = useState(0);

  return (
    <div>
      <p>Счётчик: {count}</p>
      <button onCl ick={() => setCount(count + 1)}>Увеличить</button>
    </div>
  );
};

Особенности работы с хуками:

  • Хуки можно использовать только внутри функционального компонента.
  • Порядок вызова хуков должен быть одинаковым при каждом рендере.
  • useState возвращает массив из текущего значения и функции для его обновления.

События

Функциональные компоненты могут генерировать и обрабатывать события с помощью стандартного JSX:

interface ToggleProps {
  onToggle?: (active: boolean) => void;
}

const Toggle: FunctionalComponent<ToggleProps> = ({ onToggle }) => {
  const [active, setActive] = useState(false);

  const handleClick = () => {
    const newState = !active;
    setActive(newState);
    onToggle?.(newState);
  };

  return <button onCl ick={handleClick}>{active ? 'Включено' : 'Выключено'}</button>;
};

Особенности:

  • События можно передавать через пропсы.
  • Стрелочные функции внутри JSX обеспечивают доступ к локальной области видимости.

Стилизация

Функциональные компоненты можно стилизовать с использованием обычных CSS-файлов или CSS-модулей:

import { h, FunctionalComponent } from '@stencil/core';
import styles from './my-component.css';

const MyComponent: FunctionalComponent = () => {
  return <div class={styles.wrapper}>Контент</div>;
};

Особенности:

  • Использование class вместо className.
  • Scoped CSS работает через стандартные механизмы Stencil.
  • Возможна интеграция с CSS-in-JS библиотеками.

Комбинирование функциональных компонентов

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

const Header: FunctionalComponent = () => <header>Заголовок</header>;
const Footer: FunctionalComponent = () => <footer>Подвал</footer>;

const Layout: FunctionalComponent = () => (
  <div>
    <Header />
    <main>Основной контент</main>
    <Footer />
  </div>
);

Преимущества композиции:

  • Повторное использование небольших компонентов.
  • Упрощение структуры кода и логики.
  • Лёгкость тестирования отдельных частей интерфейса.

Отличия от классовых компонентов

Характеристика Функциональные Классовые
Состояние useState this.state
Жизненный цикл useEffect componentDidMount, componentWillLoad и др.
Простота Минимум кода Больше шаблона
Типизация FunctionalComponent @Prop() + @State()

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

Рекомендации по структуре

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

Функциональные компоненты в Stencil обеспечивают современный, лаконичный и гибкий подход к разработке веб-компонентов, позволяя объединять реактивность, композицию и строгую типизацию без лишней сложности.