Skip to content

Компоненты

Компоненты являются строительными блоками для построения JSX разметки. Каждый компонент представляет собой функцию, реализующую тип PC (для синхронных компонентов) или APC (для асинхронных компонентов). Первым аргументом в такую функцию приходят параметры, а вторым - доступные утилиты PreffX.

Особенности реализации:

  1. Реактивность: Использует систему сигналов (@preact/signals-core) для создания и отслеживания реактивных значений. Только такие значения вызывают перерисовку.
  2. Управление жизненным циклом: Запускает колбеки при монтировании и удалении компонента и автоматически удаляет эффекты
  3. Передача утилит PreffX в качестве второго аргумента: Все, что необходимо, приходит в параметрах, из самого PreffX нужно импортировать только типы
  4. Поддержка асинхронных функций: Работает как с синхронными, так и с асинхронными функциями, автоматические перерисовывая DOM-дерево при разрешении промиса

Базовая реализация

Простейшая реализация компонента со счетчиком выглядит следующим образом:

typescript
import type { PC } from 'preffx';

const MyComponent: PC = (props, { signal, computed }) => {
    const { initialCount = 0 } = props;
    const count = signal(initialCount);
    
    return (
        <div>
            <p>Счетчик: {count}</p>
            <button onClick={() => count.value++}>Увеличить</button>
        </div>
    );
};

const App: PC = () => {
    return <MyComponent
        initialCount={5}
    />;
};

Реактивность

Для обеспечения реактивности используются функции, реализованные поверх @preact/signals-core, например:

  • signal - создает реактивный сигнал для состояния,
  • computed - вычисляет зависимые значения,
  • effect - управляет побочными эффектами.

Эти и другие функции полностью реализуют поведение, описанное в документации Preact Signals.

Контекст компонента

Для каждого экземпляра компонента создается свой контекст, который расширяет контекст родителя. Это обычный объект, который можно взять из утилит:

tsx
import type { PC } from 'preffx';

const contextKey = 'ctx-counter';

const AnotherComponent: PC = (props, { context }) => {
    // read context
    const counter = context[contextKey];
    return <span>
        {counter}
    </span>;
};

export const App: PC = (props, { signal, context }) => {
    const counter = signal(0);
    // modify context
    context[contextKey] = counter;
    return <p>
        {valueFromContext}
        <AnotherComponent />
    </p>;
};

Жизненный цикл

Каждый компонент может использовать утилиты жизненного цикла:

  • onMount - вызывается при монтировании компонента - после того, как его элементы будут добавлены в DOM-дерево;
  • onDestroy - вызывается при удалении компонента - перед тем, как его элементы будут удалены из DOM-дерева
tsx
import type { PC } from 'preffx';

export const App: PC = (props, { onMount, onDestroy }) => {
    const { count } = props;

    onMount(() => {
        // some mount logic
    });
    
    onDestroy(() => {
        // some destroy logic
    });
    return <button
        onClick={() => {
            count.value += 1
        }}
    >
        Count is {count}
    </button>
};

Генерация идентификаторов

Утилита id позволяет генерировать уникальные идентификаторы для использования внутри компонента:

tsx
import type { PC } from 'preffx';

export const App: PC = (props, { id }) => {
    // get unique id
    const inputId = id();
    return <>
        <label>
            Password:
            <input
                type="password"
                aria-describedby={inputId}
            />
        </label>
        <p id={inputId}>
            The password should contain at least 18 characters
        </p>
    </>;
};

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

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

  • Catch - для обработки ошибок в компонентах,
  • For - для рендеринга списков с поддержкой реактивности,
  • Defer - для отложенного рендеринга значений, которые вычисляются асинхронно,
  • Portal - для рендеринга элементов вне корня PreffX

Опубликовано под лицензией Apache License 2.0