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?