Skip to content

Instantly share code, notes, and snippets.

@noghartt
Created August 5, 2022 15:23
Show Gist options
  • Save noghartt/633760035ff41a3a6fcf5ecece2f4fcc to your computer and use it in GitHub Desktop.
Save noghartt/633760035ff41a3a6fcf5ecece2f4fcc to your computer and use it in GitHub Desktop.
@tanstack/table + @tanstack/virtual@beta + @mui/material v5 | A table with infinite scrolling and virtualized rows
import Paper from '@mui/material/Paper';
import Table from '@mui/material/Table';
import TableBody from '@mui/material/TableBody';
import TableCell from '@mui/material/TableCell';
import TableContainer from '@mui/material/TableContainer';
import TableHead from '@mui/material/TableHead';
import TableRow from '@mui/material/TableRow';
import {
useReactTable,
getCoreRowModel,
flexRender,
} from '@tanstack/react-table';
import { useVirtualizer } from '@tanstack/react-virtual';
import { useMemo, useState, useRef, useEffect } from 'react';
const Table = () => {
const { data, hasNext, isLoadingNext, loadNext } = useQuery(
// do your magic here
);
const columns = useMemo(() => [
// your columns here
], []);
const table = useReactTable({
data,
columns,
getCoreRowModel: getCoreRowModel(),
});
const tableContainerRef = useRef<HTMLDivElement>(null);
const { rows } = table.getRowModel();
const rowVirtualizer = useVirtualizer({
count: rows.length,
getScrollElement: () => tableContainerRef.current,
estimateSize: () => 100,
});
useEffect(() => {
const [lastItem] = [...rowVirtualizer.getVirtualItems()].reverse();
if (!lastItem) {
return;
}
if (lastItem.index >= rows.length - 1 && hasNext && !isLoadingNext) {
loadNext(10);
}
}, [
loadNext,
hasNext,
rows.length,
rowVirtualizer.getVirtualItems(),
isLoadingNext,
]);
return (
<TableContainer
ref={tableContainerRef}
component={Paper}
sx={{
width: '100%',
height: '100vh',
overflow: 'auto',
}}
>
<Table
sx={{
width: '100%',
height: `${rowVirtualizer.getTotalSize()}px`,
position: 'relative',
}}
>
<TableHead>
{table.getHeaderGroups().map((headerGroup) => (
<TableRow key={headerGroup.id}>
{headerGroup.headers.map((header) => (
<TableCell
component='th'
key={header.id}
colSpan={header.colSpan}
style={{ width: header.getSize() }}
>
{flexRender(
header.column.columnDef.header,
header.getContext(),
)}
</TableCell>
))}
</TableRow>
))}
</TableHead>
<TableBody>
{rowVirtualizer.getVirtualItems().map((virtualRow) => {
const row = rows[virtualRow.index - 1];
return (
<TableRow
key={virtualRow.key}
style={{
position: 'absolute',
top: 0,
left: 0,
width: '100%',
transform: `translateY(${virtualRow.start}px)`,
}}
>
{row?.getVisibleCells()?.map((cell) => (
<TableCell
key={cell?.id}
style={{
width: cell.column.getSize(),
}}
>
{flexRender(
cell?.column?.columnDef?.cell,
cell?.getContext(),
)}
</TableCell>
))}
</TableRow>
);
})}
</TableBody>
</Table>
</TableContainer>
);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment