Lazy loading/Infinite scrolling
Load data based on the visible viewport of the grid
CanvasGrid invokes onViewPortChange
callback whenever user scrolls or pans around the spreadsheet.
This can be used to load data for the next set of visible rows.
import { CanvasGrid } from "@rowsncolumns/spreadsheet"
const App = () => {
const [ sheetData, onChangeSheetData ] = useState<SheetData<T>>({})
<CanvasGrid
onViewPortChange={(viewport: ViewPortProps) => {
const {
columnStartIndex,
columnStopIndex,
rowStartIndex,
rowStopIndex,
visibleColumnStartIndex,
visibleColumnStopIndex,
visibleRowStartIndex,
visibleRowStopIndex
} = viewport
// Throttle fetch request
// Move it out of the render loop, this is just an example
throttle(
fetch(`/rows?start=${rowStartIndex}&end=${rowStopIndex}`)
.then(rowData => {
// Append new row data
onChangeSheetData(prev => {
const newRowData = prev[sheetId]
.splice(rowStartIndex, rowStopIndex - rowStartIndex, ...rowData)
return {
...prev,
[sheetId]: newRowData
}
})
})
, 300)
}}
/>
}
Hooks for Lazy loading
@rowsncolumns/spreadsheet-state
exports the useAsyncDatasource
hook to easily load an asynchronous paged data source
Usage
import { useSpreadsheetState, useAsyncDataSource } from '@rowsncolumnse/spreadsheet-state'
import { CircularLoader } from '@rowsncolumns/ui'
const App = () => {
const locale = 'en-US'
const [sheets, onChangeSheets] = useState<Sheet[]>(mockSheets);
const [sheetData, onChangeSheetData] = useState<SheetData<CellData>>({});
const { enqueueCalculation, activeSheetId } = useSpreadsheetState({
sheets,
sheetData,
onChangeSheetData,
onChangeSheets
})
const { onViewPortChange, isLoading } = useAsyncDatasource<CellData>({
sheetId: activeSheetId,
locale,
onChangeSheetData,
enqueueCalculation,
getRowData: useCallback(
async (sheetId, [rowStartIndex, rowStopIndex]) => {
await new Promise((res) => setTimeout(res, 1000));
return [
null,
{
values: [
null,
{
userEnteredValue: {
formulaValue: "=SUM(E11,4)",
},
},
],
},
];
},
[]
),
});
return (
<>
<CanvasGrid
onViewPortChange={onViewPortChange}
/>
{isLoading ? (
<CircularLoader className="absolute left-1/2 bottom-1/2 z-10 bg-rnc-background/60 border-solid border-px border-rnc-border p-5 rounded-md" />
) : null}
</>
)
}
Last updated
Was this helpful?