Виртуализация списков — это техника оптимизации рендеринга длинных списков элементов в пользовательских интерфейсах. Вместо того чтобы рендерить все элементы одновременно, виртуализация отображает только те элементы, которые видимы пользователю в данный момент, динамически подгружая и удаляя элементы при прокрутке. Это существенно снижает нагрузку на DOM и повышает производительность приложений на React, особенно при работе с тысячами элементов.
MUI напрямую не предоставляет собственные компоненты для виртуализации, однако интеграция с библиотеками React Window и React Virtualized является стандартной практикой. MUI предоставляет стилизованные обертки, которые позволяют использовать свои компоненты List, ListItem и другие элементы с виртуализацией.
FixedSizeList (react-window) —
отображает элементы фиксированной высоты.VariableSizeList (react-window) —
поддерживает элементы с различной высотой.Grid (react-window) — позволяет
виртуализировать сетки элементов.npm install @mui/material react-window
import * as React from 'react';
import { FixedSizeList as List } from 'react-window';
import ListItem from '@mui/material/ListItem';
import ListItemText from '@mui/material/ListItemText';
const items = Array.from({ length: 10000 }, (_, index) => `Элемент ${index + 1}`);
function VirtualizedList() {
const Row = ({ index, style }) => (
<ListItem style={style} key={index} divider>
<ListItemText primary={items[index]} />
</ListItem>
);
return (
<List
height={600} // Высота контейнера списка
itemCount={items.length}
itemSize={50} // Высота одного элемента
width="100%" // Ширина контейнера
>
{Row}
</List>
);
}
export default VirtualizedList;
В этом примере:
height задает высоту видимой области
списка.itemCount — общее количество
элементов.itemSize — фиксированная высота
каждого элемента.style — обязательно передается каждому
ListItem, чтобы корректно позиционировать элементы.Для элементов с разной высотой используется
VariableSizeList:
import { VariableSizeList as List } from 'react-window';
const getItemSize = index => (index % 2 === 0 ? 60 : 40);
<List
height={600}
itemCount={items.length}
itemSize={getItemSize}
width="100%"
>
{Row}
</List>
getItemSize возвращает высоту элемента по его индексу,
что позволяет корректно отображать элементы разного размера.
MUI Table можно комбинировать с виртуализацией, используя
react-window или react-virtualized. Для таблиц
с большим количеством строк рекомендуется использовать:
FixedSizeList для строк одинаковой
высоты.VariableSizeList для строк с
переменной высотой.Пример виртуализированной таблицы:
import Table from '@mui/material/Table';
import TableBody from '@mui/material/TableBody';
import TableCell from '@mui/material/TableCell';
import TableRow from '@mui/material/TableRow';
import { FixedSizeList as List } from 'react-window';
const rows = Array.from({ length: 10000 }, (_, index) => ({
id: index,
name: `Имя ${index + 1}`,
value: Math.floor(Math.random() * 1000),
}));
const Row = ({ index, style }) => (
<TableRow style={style} key={rows[index].id}>
<TableCell>{rows[index].id}</TableCell>
<TableCell>{rows[index].name}</TableCell>
<TableCell>{rows[index].value}</TableCell>
</TableRow>
);
<List
height={600}
itemCount={rows.length}
itemSize={50}
width="100%"
>
{Row}
</List>
style каждому элементу
обязательна, иначе виртуализация сломается.key критично для
корректной идентификации элементов при перерисовках.VariableSizeList.Виртуализация можно комбинировать с ленивой подгрузкой данных. Вместо загрузки всех 10 000 элементов сразу, данные могут подгружаться порциями:
itemCount и массива элементов для
виртуализированного списка.Эта стратегия снижает нагрузку на сеть и память, сохраняя отзывчивость интерфейса.
Виртуализированные списки корректно обрабатывают клики, фокус и навигацию клавиатурой, если:
key.Row.MUI полностью поддерживает свою систему стилей и темы:
sx для стилизации каждого элемента:<ListItem sx={{ bgcolor: index % 2 ? 'grey.100' : 'white' }}>
<ListItemText primary={items[index]} />
</ListItem>
Комбинация MUI с react-window предоставляет:
Эта техника является стандартом для создания масштабируемых интерфейсов с динамическими и объемными данными.