Optimizing Large Datasets with Lazy Loading in React TanStack Table
Demonstrate how to implement lazy loading of data in React TanStack Table to optimize the performance when working with large datasets and faceted search.
import { useTable, useAsyncDebounce } from '@tanstack/table-core';
import { useEffect, useState } from 'react';
function fetchData({ pageIndex, pageSize, globalFilter }) {
// simulate an API call
return new Promise(resolve => {
setTimeout(() => {
// Mocked API response
const startRow = pageIndex * pageSize;
const endRow = startRow + pageSize;
// Filter data based on globalFilter, then slice for pagination
resolve(fakeDatabase.filter(row => row.name.includes(globalFilter)).slice(startRow, endRow));
}, 1000);
});
}
Defines a mock fetchData function to simulate fetching paginated and filtered data from an API or database. It accepts an object with pageIndex, pageSize, and globalFilter as parameters.
const [data, setData] = useState([]);
const [pageCount, setPageCount] = useState(0);
const [loading, setLoading] = useState(false);
const fetchIdRef = useRef(0);
const {
getTableProps,
getTableBodyProps,
headerGroups,
rows,
prepareRow,
// Fetch the state defined for pagination
state: { pageIndex, pageSize, globalFilter },
// Use 'setGlobalFilter' from useAsyncDebounce for efficient filtering
setGlobalFilter,
} = useTable(
{
columns,
data,
initialState: { pageIndex: 0 },
manualPagination: true, // Tell the table you'll handle pagination manually
pageCount: pageCount,
},
useGlobalFilter, // Use the useGlobalFilter hook
usePagination
);
Initializes the table instance with the useTable hook. Specifies columns and data for the table, along with setting up manual pagination and filtering. The state includes pageIndex, pageSize, and globalFilter for controlling pagination and global filtering.
useEffect(() => {
const fetchDataAsync = async () => {
setLoading(true);
const fetchId = ++fetchIdRef.current;
const result = await fetchData({ pageIndex, pageSize, globalFilter });
if (fetchId === fetchIdRef.current) {
setData(result.items);
setPageCount(Math.ceil(result.total / pageSize));
setLoading(false);
}
};
fetchDataAsync();
}, [pageIndex, pageSize, globalFilter]);
Uses the useEffect hook to fetch data asynchronously whenever the pageIndex, pageSize, or globalFilter changes. Uses a fetchIdRef to ensure only the latest request updates the state to prevent race conditions.
const onSearchChange = useAsyncDebounce(value => {
setGlobalFilter(value || undefined);
}, 200);
Utilizes useAsyncDebounce to wrap setGlobalFilter, introducing a 200ms delay before applying the filter. This helps in reducing the frequency of calls made to filter the data as the user types.