Виртуализация — это метод оптимизации отображения больших списков и
таблиц в интерфейсе, при котором рендерятся только те элементы, которые
видимы пользователю в данный момент. Это снижает нагрузку на DOM и
повышает производительность приложений на React. В MUI
виртуализация реализуется через компоненты Table,
List, а также через интеграцию с библиотеками вроде
react-window и react-virtualized.
Рендеринг только видимых элементов В отличие от обычного списка, где все элементы создаются в DOM, виртуализированный список создаёт только элементы, которые находятся в области видимости. Элементы за пределами окна просмотра заменяются на “пустые” контейнеры фиксированной высоты, чтобы сохранить скролл.
Фиксированная высота или динамическая
Виртуализация работает эффективнее при известной фиксированной высоте
элементов. Если элементы имеют переменную высоту, необходимо
использовать методы, которые поддерживают динамическое измерение,
например VariableSizeList из
react-window.
Буферизация Для предотвращения мерцания при скролле используется буфер — элементы перед и после видимой области создаются заранее, что обеспечивает плавность прокрутки.
MUI не содержит собственного встроенного механизма полной
виртуализации, но компоненты MUI легко интегрируются с
react-window:
import 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={400}
itemCount={items.length}
itemSize={50}
width={'100%'}
>
{Row}
</List>
);
}
export default VirtualizedList;
Пояснение к коду:
height — высота видимой области списка.itemCount — общее количество элементов.itemSize — высота одного элемента (фиксированная).Row — компонент для рендеринга одной строки с учетом
переданных стилей style.Для больших таблиц MUI предлагает сочетание компонентов
Table, TableBody, TableCell с
виртуализацией через react-window. Основной подход:
FixedSizeList для обертки строк
таблицы.TableRow
внутри списка.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 VirtualizedTable = ({ rows }) => {
const Row = ({ index, style }) => (
<TableRow style={style} key={index}>
<TableCell>{rows[index].name}</TableCell>
<TableCell>{rows[index].age}</TableCell>
<TableCell>{rows[index].email}</TableCell>
</TableRow>
);
return (
<Table>
<TableBody>
<List
height={400}
itemCount={rows.length}
itemSize={50}
width="100%"
>
{Row}
</List>
</TableBody>
</Table>
);
};
React.memo уменьшает повторный рендер при прокрутке.outerElementType и
innerElementType в react-window
позволяет заменить стандартные контейнеры на MUI-совместимые элементы,
сохраняя стили.styled и
sx пропсы. При виртуализации важно передавать
style от виртуализатора, чтобы позиционирование оставалось
корректным.ListItemButton,
TableRow) могут иметь эффекты при наведении. Для сохранения
визуальной согласованности нужно комбинировать style
виртуализатора с MUI классами.Collapse внутри
TableRow) требуют отдельного контроля высоты для
корректного отображения.MUI предоставляет компонент Masonry
(для сеточных списков), который поддерживает ленивую отрисовку:
import Masonry from '@mui/lab/Masonry';
import Box from '@mui/material/Box';
const items = Array.from({ length: 1000 }, (_, i) => i);
<Masonry columns={4} spacing={2}>
{items.map((item) => (
<Box key={item} sx={{ bgcolor: 'primary.main', height: 100 }} />
))}
</Masonry>
Компонент Masonry автоматически рендерит только видимые
элементы, что облегчает работу с крупными сетками изображений или
карточек.
react-window или
react-virtualized для больших таблиц и списков.React.memo и буферизацию для плавной
прокрутки.Masonry из
@mui/lab.Эти подходы позволяют создавать интерфейсы, которые остаются отзывчивыми даже при десятках тысяч элементов.