Fallback контент

Fallback контент — это механизм, позволяющий компоненту предоставлять запасной вариант отображения, если определённые условия не выполнены или данные ещё не загружены. В Atomico он реализуется через комбинацию slots, условного рендеринга и специальных утилит для управления состоянием компонентов.

Slots и fallback

Atomico использует концепцию слотов, аналогичную Web Components. Слот позволяет вставлять внешний контент в компонент. Для задания fallback контента используется структура по умолчанию:

import { c, html } from "atomico";

function Card({ title, content }) {
    return html`
        <div class="card">
            <h2>${title || html`<slot name="title">Заголовок отсутствует</slot>`}</h2>
            <p>${content || html`<slot name="content">Контент загружается...</slot>`}</p>
        </div>
    `;
}

Card.props = {
    title: String,
    content: String
};

export const card = c(Card);

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

  • Если title не передан, используется слот с fallback текстом.
  • Слот content выводит запасное сообщение при отсутствии данных.

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

Условный рендеринг

Fallback контент часто комбинируется с условным рендерингом. Atomico предоставляет возможности для управления состоянием через обычные JavaScript-конструкции и реактивные свойства:

import { c, html, useState } from "atomico";

function LoaderExample() {
    const [data, setData] = useState(null);

    setTimeout(() => setData("Данные загружены"), 2000);

    return html`
        <div>
            ${data ? html`<p>${data}</p>` : html`<p>Загрузка...</p>`}
        </div>
    `;
}

export const loaderExample = c(LoaderExample);

Здесь:

  • data инициализируется как null.
  • Пока данные не загружены, отображается fallback текст «Загрузка…».
  • После получения данных отображается основной контент.

Использование fallback для асинхронных компонентов

Atomico поддерживает динамическую загрузку компонентов через lazy и Suspense-подобные конструкции. Для асинхронного рендеринга fallback контент незаменим:

import { c, html, lazy } from "atomico";

const AsyncComponent = lazy(() => import("./AsyncComponent"));

function App() {
    return html`
        <div>
            <${AsyncComponent}>
                <span slot="fallback">Загрузка компонента...</span>
            <//>
        </div>
    `;
}

export const app = c(App);

Механизм работает следующим образом:

  • Пока AsyncComponent не загружен, отображается слот с slot="fallback".
  • После загрузки основной компонент заменяет fallback автоматически.

Стилизация fallback

Для повышения UX часто требуется отдельная стилизация fallback контента. Atomico позволяет привязывать CSS непосредственно к состоянию элемента:

import { c, html, useState } from "atomico";
import css from "atomico/css";

const style = css`
    .fallback {
        color: gray;
        font-style: italic;
    }
`;

function StyledFallback({ loaded }) {
    return html`
        <div class="${style}">
            ${loaded ? html`<p>Контент готов</p>` : html`<p class="fallback">Подождите...</p>`}
        </div>
    `;
}

export const styledFallback = c(StyledFallback);

Принципы использования

  1. Минимизация пустого рендеринга Всегда предоставлять информативный fallback, чтобы интерфейс не выглядел «мертвым».

  2. Согласованность с UX Стиль и поведение fallback контента должны соответствовать дизайну приложения.

  3. Асинхронная готовность Для компонентов с динамической загрузкой обязательно использовать fallback, чтобы избежать визуальных «прыжков» контента.

  4. Комбинирование с props Fallback может быть либо встроенным в компонент, либо переданным через props или слоты, что повышает гибкость и повторное использование.

Практический пример

import { c, html, useState } from "atomico";

function ProfileCard({ user }) {
    const [loading, setLoading] = useState(true);

    setTimeout(() => setLoading(false), 1500);

    return html`
        <div class="profile-card">
            ${loading 
                ? html`<p>Загрузка профиля...</p>` 
                : html`
                    <h3>${user.name}</h3>
                    <p>${user.bio}</p>
                `}
        </div>
    `;
}

ProfileCard.props = {
    user: Object
};

export const profileCard = c(ProfileCard);

В данном примере fallback текст «Загрузка профиля…» обеспечивают плавный переход между состояниями, без резких изменений интерфейса, что является ключевым при работе с динамическими данными в Atomico.