# Virtual Scrolling

Virtual scrolling is an alternative to paging for large data sets. It uses DOM virtualization to render only the visible rows, which keeps scrolling smooth and improves performance without displaying all records in the DOM at once.

<CtaPanelOverview></CtaPanelOverview>

As of KendoReact 11.0.0, the Grid's default [`scrollable`](https://www.telerik.com/kendo-react-ui-develop/components/grid/api/gridprops#scrollable) mode is set to `virtual` for licensed users. To explicitly enable virtual scrolling, set the Grid `scrollable` option to `virtual` and specify the Grid height through the [`style`](https://www.telerik.com/kendo-react-ui-develop/components/grid/api/gridprops#style) prop. When you also provide values such as `skip` and `pageSize`, the Grid uses them to determine which records should be rendered in the current virtual range.

The following example demonstrates how to implement virtual scrolling in the Grid, where only the visible rows are rendered as the user scrolls through the data.

[Demo Source](https://demos.telerik.com/kendo-react-ui/grid/virtual-scrolling-overview/func/source.txt)

## Configuration Options

After you enable virtual scrolling, configure the following props based on your data source and layout requirements.

* [`skip`](https://www.telerik.com/kendo-react-ui-develop/components/grid/api/gridprops#skip) — Sets how many records are skipped before the current virtual page. This is useful when you control the current virtual range through state.
* [`take`](https://www.telerik.com/kendo-react-ui-develop/components/grid/api/gridprops#take) — Defines how many records are rendered in the current view.
* [`total`](https://www.telerik.com/kendo-react-ui-develop/components/grid/api/gridprops#total) — Sets the full number of records so the scrollbar can represent the complete range.
* [`pageSize`](https://www.telerik.com/kendo-react-ui-develop/components/grid/api/gridprops#pagesize) — Sets how many records are requested for each virtual page.
* [`rowHeight`](https://www.telerik.com/kendo-react-ui-develop/components/grid/api/gridprops#rowheight) — Sets the height of each row. Use a fixed row height so the Grid can calculate the virtual layout correctly.
* [`detailRowHeight`](https://www.telerik.com/kendo-react-ui-develop/components/grid/api/gridprops#detailrowheight) — Sets the height of each detail row when [detail rows](https://www.telerik.com/kendo-react-ui-develop/components/grid/rows/detail) are enabled.
* [`showLoader`](https://www.telerik.com/kendo-react-ui-develop/components/grid/api/gridprops#showloader) — Displays the built-in loading overlay while remote data is being fetched.
* [`loader`](https://www.telerik.com/kendo-react-ui-develop/components/grid/api/gridprops#loader) — Replaces the default loading overlay with a custom loader component.

Depending on your scenario, use the following sections:

| Section                                                                                                                                                                          | Description                                                                                                                         |
| -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------- |
| [Virtualization with Local Data](https://www.telerik.com/kendo-react-ui-develop/components/grid/scroll-modes/virtual#virtualization-with-local-data)                             | Use this setup when all data is already available in memory and virtualization is mainly used to reduce DOM rendering work.         |
| [Virtualization with Remote Data](https://www.telerik.com/kendo-react-ui-develop/components/grid/scroll-modes/virtual#virtualization-with-remote-data)                           | Bind the Grid to the currently loaded page, handle `onPageChange`, and show loading feedback while the next range is being fetched. |
| [Using Virtualization with Grouping](https://www.telerik.com/kendo-react-ui-develop/components/grid/scroll-modes/virtual#using-virtualization-with-grouping)                     | Combine virtual scrolling with grouped data and process the grouped result locally or on the server.                                |
| [Using Virtualization with Detail Rows](https://www.telerik.com/kendo-react-ui-develop/components/grid/scroll-modes/virtual#using-virtualization-with-detail-rows)               | Keep detail rows compatible with virtualization by configuring the expand state and detail row height.                              |
| [Using Virtualization with Responsive Columns](https://www.telerik.com/kendo-react-ui-develop/components/grid/scroll-modes/virtual#using-virtualization-with-responsive-columns) | Preserve virtual scrolling while adapting cell templates to different column widths.                                                |
| [Debouncing PageChange Events](https://www.telerik.com/kendo-react-ui-develop/components/grid/scroll-modes/virtual#debouncing-pagechange-events)                                 | Reduce unnecessary remote requests when users scroll quickly through large result sets.                                             |

Each section below includes configuration guidance and a live example for that virtualization scenario.

## Virtualization with Local Data

Use this setup when the full data set is already available in memory and virtualization is needed mainly to reduce DOM rendering work. Bind the Grid `data` property to the local collection, then use the virtual paging settings such as `skip`, `pageSize`, and `total` together with the [`onPageChange`](https://www.telerik.com/kendo-react-ui-develop/components/grid/api/gridprops#onpagechange) handler to control which part of the collection is currently visible. In this mode, scrolling updates the visible slice of the already loaded data, so the Grid can stay responsive without requesting additional records.

The following example demonstrates basic virtual scrolling with locally loaded data, where only the visible rows are rendered as the user scrolls.

[Demo Source](https://demos.telerik.com/kendo-react-ui/grid/virtual-scrolling-local/func/source.txt)

This setup works best when the full data set is already available in memory and the main bottleneck is DOM rendering rather than data retrieval.

## Virtualization with Remote Data

When the data comes from a remote service, bind the Grid `data` property to the currently loaded page and keep the virtual paging state in your application. Then implement the [`onPageChange`](https://www.telerik.com/kendo-react-ui-develop/components/grid/api/gridprops#onpagechange) handler so it requests the records needed for the next visible range as the user scrolls. This allows the Grid to fetch and display only the required data while preserving the continuous virtual scrolling experience.

The following example demonstrates virtual scrolling with remotely loaded data and skeleton cells as loading placeholders.

[Demo Source](https://demos.telerik.com/kendo-react-ui/grid/virtual-scrolling-remote/func/source.txt)

While the request is in progress, the Grid can render skeleton cells for rows whose data has not yet arrived. Alternatively, set `showLoader={true}` to show a loading overlay, use the `loader` prop to supply a custom component, or omit it to use the built-in one. For more details, see the [Loading Indicator](https://www.telerik.com/kendo-react-ui-develop/components/grid/interactivity/loading-indicator) article.

```tsx
<Grid showLoader={true} loader={<div>Loading...</div>} />
```

If the remote endpoint is slower or users scroll aggressively, see [Debouncing PageChange Events](https://www.telerik.com/kendo-react-ui-develop/components/grid/scroll-modes/virtual#debouncing-pagechange-events) to limit unnecessary requests.

## Using Virtualization with Grouping

You can use virtual scrolling in combination with grouped data.

1. Set the [`groupable`](https://www.telerik.com/kendo-react-ui-develop/components/grid/api/gridprops#groupable) and [`group`](https://www.telerik.com/kendo-react-ui-develop/components/grid/api/gridprops#group) options of the Grid.
2. Set the [`scrollable`](https://www.telerik.com/kendo-react-ui-develop/components/grid/api/gridprops#scrollable) option to `virtual`.
3. Handle the emitted [`onDataStateChange`](https://www.telerik.com/kendo-react-ui-develop/components/grid/api/gridprops#ondatastatechange) event. The `onDataStateChange` event fires upon user interaction with the scrolling or changing the groups, and then processes the data and returns the data to the Grid.

To programmatically implement the processing of the data, either:

* Send a request to the server to execute the grouping on the server side, or
* Use the `process` method of the [`DataQuery`](https://www.telerik.com/kendo-react-ui-develop/components/dataquery) library which automatically processes the data.

The Grid expects the grouped data to be a collection of [`GroupResults`](https://www.telerik.com/kendo-react-ui-develop/components/dataquery/api/groupresult).

The following example demonstrates virtual scrolling combined with data grouping, where the visible grouped rows are rendered on demand as the user scrolls.

[Demo Source](https://demos.telerik.com/kendo-react-ui/grid/grouping-virtual/func/source.txt)

## Using Virtualization with Detail Rows

You can also use [DOM virtualization](https://www.telerik.com/kendo-react-ui-develop/components/grid/scroll-modes/virtual#virtual-scrolling) in combination with [detail rows](https://www.telerik.com/kendo-react-ui-develop/components/grid/rows/detail).

1. Set the [`detail`](https://www.telerik.com/kendo-react-ui-develop/components/grid/api/gridprops#detail) to the detail component.
2. Set the [`detailExpand`](https://www.telerik.com/kendo-react-ui-develop/components/grid/api/gridprops#detailexpand) prop to handle the expand state of the Grid internally.
3. Handle [`onDetailExpandChange`](https://www.telerik.com/kendo-react-ui-develop/components/grid/api/gridprops#ondetailexpandchange) and set [`detailRowHeight`](https://www.telerik.com/kendo-react-ui-develop/components/grid/api/gridprops#detailrowheight) so the virtual layout can account for the expanded content.

The following example demonstrates virtual scrolling with expandable detail rows, where the detail content is revealed inline without breaking the scroll position.

[Demo Source](https://demos.telerik.com/kendo-react-ui/grid/detail-rows-virtualization/func/source.txt)

## Using Virtualization with Responsive Columns

The virtual scrolling functionality requires that all Grid rows have an equal, predefined height. However, you can still keep virtual scrolling and use responsive columns which have different cell templates based on the column width.

The following example demonstrates virtual scrolling with responsive column templates that adapt their content based on the column width.

[Demo Source](https://demos.telerik.com/kendo-react-ui/grid/responsive-design/column-virtualization/source.txt)

## Debouncing PageChange Events

When configured for virtualization, the Grid fires the [`onPageChange`](https://www.telerik.com/kendo-react-ui-develop/components/grid/api/gridprops#onpagechange) event as often as possible. This behavior allows for a smoother scrolling experience when the data is available in memory.

If the data is requested from a remote service, debounce or otherwise limit the page changes so rapid scrolling does not trigger unnecessary requests. This is especially useful when the backend is slower or when you want to reduce traffic while users scroll through large result sets.

The following example demonstrates remote virtual scrolling with a debounced `onPageChange` handler.

[Demo Source](https://demos.telerik.com/kendo-react-ui/grid/virtual-scrolling-remote-debounce/func/source.txt)

## Suggested Links

* [API Reference of the Grid](https://www.telerik.com/kendo-react-ui-develop/components/grid/api/gridprops)
* [API Index of the Grid](https://www.telerik.com/kendo-react-ui-develop/components/grid/api)
