Виртуализация списков

В больших приложениях работа с длинными списками данных может серьёзно влиять на производительность. Если рендерить сотни или тысячи элементов одновременно, DOM быстро становится перегруженным, а интерфейс замедляется. В таких случаях библиотека Ant Design предоставляет встроенные механизмы виртуализации списков, которые позволяют рендерить только видимую часть элементов, значительно ускоряя работу приложения.


Компонент List с виртуализацией

Ant Design поддерживает виртуализацию через использование свойства virtual в компоненте List. Для работы с виртуализированными списками необходимо подключить также модуль rc-virtual-list, который интегрирован с Ant Design.

Пример базовой настройки:

import React from 'react';
import { List } from 'antd';
import VirtualList from 'rc-virtual-list';

const data = Array.from({ length: 10000 }, (_, i) => `Элемент ${i}`);

const ContainerHeight = 400;

export default function VirtualizedList() {
  return (
    <List>
      <VirtualList
        data={data}
        height={ContainerHeight}
        itemHeight={47}
        itemKey="id"
      >
        {(item) => (
          <List.Item key={item}>
            {item}
          </List.Item>
        )}
      </VirtualList>
    </List>
  );
}

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

  • height — высота контейнера списка. Это высота области, в которой отображаются элементы.
  • itemHeight — фиксированная высота одного элемента. Это важно для корректной виртуализации и расчёта скролла.
  • itemKey — уникальный идентификатор для каждого элемента, необходимый для правильного обновления списка при изменении данных.

Использование динамической высоты элементов

По умолчанию виртуализация в VirtualList работает с фиксированной высотой элементов. Если элементы имеют разную высоту, нужно использовать компонент VariableSizeList из react-window совместно с Ant Design, либо рассчитывать высоту заранее и передавать её через массив. Прямой поддержки переменной высоты в rc-virtual-list нет, но можно комбинировать с кастомными решениями для сложных интерфейсов.


Поддержка событий прокрутки

Виртуализированные списки поддерживают отслеживание событий прокрутки через свойства:

  • onScroll: вызывается при скролле контейнера.
  • onReachBottom: полезно для реализации инфинити-скролла (загрузки данных по мере прокрутки).

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

<VirtualList
  data={data}
  height={ContainerHeight}
  itemHeight={47}
  itemKey="id"
  onScr oll={(e) => console.log('Scroll position:', e.currentTarget.scrollTop)}
  onReachBot tom={() => console.log('Достигнут низ списка')}
>
  {(item) => <List.Item key={item}>{item}</List.Item>}
</VirtualList>

Это позволяет эффективно подгружать новые данные, не перегружая DOM.


Интеграция с компонентами Ant Design

Виртуализация прекрасно сочетается с другими компонентами Ant Design, такими как:

  • List.Item.Meta для отображения заголовка, описания и аватара.
  • Checkbox, Button и другие интерактивные элементы внутри элементов списка.

Пример комбинированного элемента списка:

<List>
  <VirtualList
    data={data}
    height={ContainerHeight}
    itemHeight={70}
    itemKey="id"
  >
    {(item) => (
      <List.Item key={item}>
        <List.Item.Meta
          avatar={<Avatar>{item[0]}</Avatar>}
          title={`Заголовок ${item}`}
          description={`Описание элемента ${item}`}
        />
        <Button type="primary">Действие</Button>
      </List.Item>
    )}
  </VirtualList>
</List>

Оптимизация производительности

При работе с виртуализированными списками важно учитывать:

  1. Фиксированная высота элементов — обеспечивает корректный расчёт скролла.
  2. Минимизация ререндеров — использовать React.memo для компонентов списка, особенно если они сложные.
  3. Lazy Loading — подгружать данные партиями по мере прокрутки.
  4. Ключи элементовitemKey должен быть уникальным и стабильным, иначе виртуализация может некорректно обновлять DOM.

Сочетание с пагинацией

Даже при виртуализации иногда полезно комбинировать список с пагинацией Ant Design (Pagination). Это позволяет:

  • Ограничивать общий объём данных в памяти.
  • Улучшать UX для пользователей, которые хотят видеть разбивку на страницы.

Пример:

<List
  dataSource={currentPageData}
  renderItem={(item) => <List.Item>{item}</List.Item>}
  pagination={{
    current: currentPage,
    pageSize: 100,
    total: data.length,
    onChange: setPage,
  }}
/>

В этом случае виртуализация может использоваться внутри страницы, чтобы отображать только видимые элементы текущей страницы.


Практические рекомендации

  • Для больших списков (>1000 элементов) виртуализация обязательна.
  • Если элементы интерактивные (кнопки, чекбоксы), важно проверять производительность на разных устройствах.
  • Комбинация VirtualList с List.Item.Meta позволяет создавать богатые визуально элементы без потери скорости.

Использование виртуализации в Ant Design позволяет создавать масштабируемые интерфейсы, которые остаются отзывчивыми при работе с огромными объёмами данных, сохраняя удобство стандартных компонентов библиотеки и богатый функционал.