Фрагменты и порталы

Фрагменты (Fragments) в Inferno позволяют группировать несколько элементов без необходимости создавать лишний DOM-узел. Это особенно полезно при возвращении нескольких компонентов из функции рендеринга, когда обертка в <div> или другой элемент создаст лишнюю структуру в DOM.

import { Fragment } from 'inferno';

function Example() {
  return (
    <Fragment>
      <h1>Заголовок</h1>
      <p>Некоторый текст</p>
    </Fragment>
  );
}

Ключевые особенности фрагментов

  • Нет дополнительного DOM-узла: Фрагмент не создаёт элемент в дереве DOM.
  • Можно использовать ключи: Если требуется динамический список фрагментов, ключи помогают оптимизировать ререндер.
  • Совместимость с JSX: <></> — сокращённая форма записи фрагментов поддерживается JSX.
function List({ items }) {
  return (
    <>
      {items.map(item => (
        <Fragment key={item.id}>
          <h2>{item.title}</h2>
          <p>{item.description}</p>
        </Fragment>
      ))}
    </>
  );
}

Использование фрагментов позволяет избежать лишнего вложенного DOM, что положительно сказывается на производительности, особенно при больших списках компонентов.


Порталы в Inferno

Порталы (Portals) предназначены для рендеринга компонентов в DOM-узлах, находящихся за пределами основного корня приложения. Это полезно для модальных окон, всплывающих подсказок, уведомлений, когда визуальное расположение в дереве DOM должно отличаться от логической структуры компонентов.

import { render } from 'inferno';
import { createPortal } from 'inferno-create-portal';

function Modal({ children }) {
  const modalRoot = document.getElementById('modal-root');
  return createPortal(
    <div className="modal">
      {children}
    </div>,
    modalRoot
  );
}

Принципы работы порталов

  • Изоляция визуального размещения: Компонент может быть логически вложен в родителя, но визуально отображаться в другом месте DOM.
  • События и контекст: Порталы сохраняют контекст родителя, включая события и состояние. Клик по элементу внутри портала будет всплывать так, как если бы он находился внутри обычного DOM-узла компонента.
  • Поддержка JSX: Используется стандартная JSX-разметка, создаваемая функцией createPortal.
function App() {
  return (
    <div>
      <h1>Главное приложение</h1>
      <Modal>
        <p>Это модальное окно</p>
      </Modal>
    </div>
  );
}

В данном примере <Modal> будет отображаться в элементе #modal-root, но событие клика внутри него будет восприниматься как часть дерева компонента App.


Отличия фрагментов и порталов

Параметр Фрагменты Порталы
DOM-узел Не создают Рендерят в указанном узле
Использование Группировка элементов Модальные окна, всплывающие окна
Контекст Наследует контекст Сохраняет контекст родителя
Производительность Минимальное влияние Может быть дороже рендера

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


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

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