Render props паттерн

Render Props — это паттерн проектирования, позволяющий компоненту предоставлять функциональность через функцию, переданную в качестве свойства, вместо статического шаблона. В контексте SvelteKit и UI-библиотек на JavaScript этот подход обеспечивает гибкое управление визуализацией компонентов и их поведением.


Основные принципы

  1. Передача функции в компонент Компонент принимает функцию через пропс, например let renderItem = (data) => { ... }. Эта функция отвечает за рендер конкретного содержимого внутри компонента. Такой подход отделяет логику от представления.

  2. Контроль состояния Компонент управляет внутренним состоянием (например, активным элементом списка, загрузкой данных или видимостью модального окна), а render-prop функция получает доступ к этому состоянию для динамической визуализации.

  3. Гибкость переиспользования Один компонент с render-prop можно использовать с разными визуальными шаблонами без дублирования логики. Например, компонент списка можно использовать для таблицы, карточек или простого текстового списка, просто передавая разную render-функцию.


Пример реализации в SvelteKit

<!-- List.svelte -->
<script>
  export let items = [];
  export let renderItem;
  let selectedIndex = -1;

  function sel ect(index) {
    selectedIndex = index;
  }
</script>

<ul>
  {#each items as item, index}
    <li on:click={() => select(index)}>
      {#if renderItem}
        {@html renderItem({ item, index, selected: selectedIndex === index })}
      {:else}
        {item}
      {/if}
    </li>
  {/each}
</ul>
<!-- App.svelte -->
<script>
  import List fr om './List.svelte';

  const items = ['Apple', 'Banana', 'Cherry'];

  function customRenderer({ item, selected }) {
    return `<strong style="color: ${selected ? 'red' : 'black'}">${item}</strong>`;
  }
</script>

<List {items} renderItem={customRenderer} />

Пояснение:

  • Компонент List.svelte управляет состоянием выбранного элемента (selectedIndex).
  • Render-функция customRenderer получает состояние выбранного элемента и динамически изменяет стиль.
  • Это демонстрирует чистое разделение логики управления состоянием и представления.

Применение в UI-библиотеках

В современных SvelteKit UI-библиотеках render props активно используются в следующих сценариях:

  1. Модальные окна и диалоги Компонент модального окна предоставляет API для открытия и закрытия, а render-функция управляет содержимым: форма, список действий или кастомный контент.

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

  3. Компоненты с асинхронными данными Например, DataFetcher предоставляет loading, error и data через объект render-функции, а потребитель компонента решает, как отобразить эти состояния.

<!-- AsyncData.svelte -->
<script>
  export let fetchData;
  export let render;
  let data = null;
  let loading = true;
  let error = null;

  fetchData()
    .then(res => data = res)
    .catch(err => error = err)
    .finally(() => loading = false);
</script>

{#if render}
  {@html render({ data, loading, error })}
{/if}

Преимущества render props в SvelteKit

  • Полная кастомизация представления без изменения внутренней логики компонента.
  • Повторное использование логики с разными UI-шаблонами.
  • Четкое разделение ответственности, облегчает поддержку и тестирование.
  • Совместимость с асинхронными процессами и реактивным состоянием SvelteKit.

Рекомендации по использованию

  • Render-функции должны быть чистыми, не модифицировать внутреннее состояние компонента напрямую.
  • Использовать TypeScript или JSDoc для описания параметров функции, чтобы избежать ошибок при передаче объектов состояния.
  • В больших проектах применять render props совместно с slots и context API Svelte, создавая гибкие и масштабируемые компоненты.

Отличие от слотов

Хотя слоты в Svelte позволяют вставлять произвольное содержимое, render props обеспечивают доступ к внутреннему состоянию компонента через аргументы функции. Это делает паттерн идеальным для компонентов с динамическими состояниями или сложной логикой отображения.


Заключение паттерна

Render props — это мощный инструмент для построения универсальных и гибких UI-компонентов в SvelteKit. Он позволяет отделять визуализацию от логики, создавать переиспользуемые компоненты и управлять состоянием более прозрачно, особенно при работе с асинхронными данными и интерактивными элементами интерфейса.