High-performance rendering for large datasets.
Virtualization renders only visible rows in the viewport, dramatically improving performance for large datasets. The ActiveGrid automatically enables virtualization for datasets exceeding 1,000 rows.
Instead of rendering all rows in the DOM, virtualization:
This allows the grid to handle datasets with 100,000+ rows smoothly.
Virtualization automatically enables when row count exceeds the threshold:
<ActiveGrid
columns={columns}
data={largeDataset} // 5,000 rows
// Virtualization automatically enabled
{...}
/>booleanfalse<ActiveGrid
enableVirtualization={true}
columns={columns}
data={data}
{...}
/>number1000<ActiveGrid
virtualizationThreshold={500} // Enable at 500 rows
columns={columns}
data={data}
{...}
/>number<ActiveGrid
virtualContainerHeight={600}
enableVirtualization={true}
columns={columns}
data={data}
{...}
/>When virtualContainerHeight is not specified, the grid calculates height based on available space.
Virtualization works seamlessly with server-side pagination:
Virtualization works best with fixed row heights. Variable row heights can cause scroll position issues.
If you need variable heights, consider:
autoHeight sparinglySet consistent row height for optimal virtualization:
The grid renders additional rows above and below the viewport (overscan) to prevent flashing during scroll. This is automatically calculated but optimized for smooth scrolling.
Combine virtualization with server-side mode for infinite scroll:
Check if virtualization is active:
Solution: Ensure consistent row heights
Solution: This is normal during very fast scrolling. Increase overscan if needed (handled automatically).
Solutions:
Virtualization significantly reduces memory usage:
Monitor memory in Chrome DevTools:
Virtualization works in all modern browsers:
Target performance with virtualization:
<ActiveGrid
mode="client"
data={largeDataset} // 50,000 rows
columns={columns}
enableVirtualization={true}
virtualContainerHeight={700}
{...}
/><ActiveGrid
mode="server"
fetchFn={async (params) => {
const response = await api.getData({
page: params.pageIndex,
limit: params.pageSize,
});
return {
data: response.data,
totalCount: response.total,
};
}}
columns={columns}
pagination={{
enabled: true,
pageSizeOptions: [50, 100, 200],
}}
initialPageSize={100}
enableVirtualization={true}
{...}
/><ActiveGrid
settings={{
rowHeight: 48,
}}
enableVirtualization={true}
{...}
/>function InfiniteScrollTable() {
const [pageSize] = useState(50);
return (
<ActiveGrid
mode="server"
fetchFn={async (params) => {
const response = await api.getData({
offset: params.pageIndex * params.pageSize,
limit: params.pageSize,
});
return {
data: response.data,
totalCount: response.total,
};
}}
columns={columns}
initialPageSize={pageSize}
enableVirtualization={true}
virtualContainerHeight={800}
pagination={{
enabled: true,
showButtons: false, // Hide pagination buttons
}}
{...}
/>
);
}// Memoize cell renderers
const columns: GridColumnDef<Data>[] = [
{
accessorKey: 'name',
header: 'Name',
cell: memo(({ getValue }) => {
return <span>{getValue()}</span>;
}),
},
];// Memoize data transformations
const processedData = useMemo(() => {
return rawData.map(item => ({
...item,
computed: expensiveCalculation(item),
}));
}, [rawData]);
<ActiveGrid data={processedData} {...} />// Memoize columns
const columns = useMemo(() => [...], []);
// Memoize callbacks
const handleRowClick = useCallback((row) => {
// Handle click
}, []);
<ActiveGrid
columns={columns}
data={data}
onRowClick={handleRowClick}
{...}
/>import { useActiveGrid } from '@workspace/active-grid';
function DebugInfo() {
const table = useActiveGrid();
const rowModel = table.getRowModel();
const virtualRows = table.getRowModel().rows;
return (
<div>
<p>Total rows: {table.getRowCount()}</p>
<p>Rendered rows: {virtualRows.length}</p>
<p>Virtualization: {virtualRows.length < table.getRowCount() ? 'Active' : 'Inactive'}</p>
</div>
);
}settings={{
rowHeight: 44,
}}// 10,000 rows without virtualization: ~100 MB
// 10,000 rows with virtualization: ~10 MBimport { useMemo } from 'react';
import { ActiveGrid, GridColumnDef } from '@workspace/active-grid';
type Data = {
id: string;
name: string;
value: number;
};
function LargeActiveGrid() {
// Generate large dataset
const data = useMemo(() => {
return Array.from({ length: 50000 }, (_, i) => ({
id: `row-${i}`,
name: `Item ${i}`,
value: Math.random() * 1000,
}));
}, []);
const columns = useMemo<GridColumnDef<Data>[]>(() => [
{
accessorKey: 'id',
header: 'ID',
size: 100,
},
{
accessorKey: 'name',
header: 'Name',
size: 200,
},
{
accessorKey: 'value',
header: 'Value',
size: 120,
meta: {
cellAlign: 'right',
valueFormatter: (value) => `$${value.toFixed(2)}`,
},
},
], []);
return (
<ActiveGrid
columns={columns}
data={data}
enableVirtualization={true}
virtualContainerHeight={700}
settings={{
rowHeight: 44,
}}
pagination={{
enabled: true,
pageSizeOptions: [50, 100, 200, 500],
}}
initialPageSize={100}
/>
);
}<ActiveGrid<Data>
columns={columns}
data={largeDataset}
enableVirtualization={true}
virtualContainerHeight={600}
virtualizationThreshold={1000}
{...}
/>