Using Memoization to Prevent Unnecessary Renders in Virtualized Table
Demonstrate the use of React's useMemo and useCallback hooks to memoize rows and columns in React TanStack Table, preventing unnecessary re-renders when virtualizing large datasets.
import React, { useMemo, useCallback } from 'react';
import { useTable } from 'react-table';
import { FixedSizeList as List } from 'react-window';
Imports React, useMemo, useCallback hooks, useTable from react-table, and List from react-window for virtualization.
const RenderRow = React.memo(({ index, style, data }) => {
const row = data[index];
return (
<div {...row.getRowProps({ style })} className="tr">
{row.cells.map(cell => {
return (
<div {...cell.getCellProps()} className="td">
{cell.render('Cell')}
</div>
)
})}
</div>
)
});
Defines a memoized row component. It only re-renders if the props change, thus preventing unnecessary renders for unchanged rows.
const Table = ({ columns, data }) => {
const defaultColumn = useMemo(() => ({
minWidth: 30,
width: 150,
maxWidth: 200
}), []);
const {
getTableProps,
getTableBodyProps,
headerGroups,
rows,
prepareRow,
} = useTable({
columns,
data,
defaultColumn
});
const RenderedRows = useCallback(({ index, style }) => <RenderRow index={index} style={style} data={rows} prepareRow={prepareRow} />, [rows, prepareRow]);
return (
<div {...getTableProps()}>
<div>
{headerGroups.map(headerGroup => (
<div {...headerGroup.getHeaderGroupProps()} className="tr">
{headerGroup.headers.map(column => (
<div {...column.getHeaderProps()} className="th">
{column.render('Header')}
</div>
))}
</div>
))}
</div>
<List
height={400}
itemCount={rows.length}
itemSize={35}
width={'100%'}
>
{RenderedRows}
</List>
</div>
);
}
Creates the table component using useTable hook. Memoizes the defaultColumn definition and useCallback for row rendering to prevent unnecessary re-renders.