---
product: "AG Grid"
title: "Loading Rows"
description: "Display skeleton rows while Client-Side Row Model data is loading."
framework: react
version: "36.2.0"
related:
    - title: "Overview"
      url: "https://www.ag-grid.com/react-data-grid/overlays-overview/"
    - title: "Provided Overlays"
      url: "https://www.ag-grid.com/react-data-grid/overlays-provided/"
    - title: "Active Overlay"
      url: "https://www.ag-grid.com/react-data-grid/overlays-active/"
llms: "https://www.ag-grid.com/llms.txt"
---

# Loading Rows

The Client-Side Row Model can display skeleton rows instead of the loading overlay while row data is loading.

#### Loading Rows

```tsx
"use client";

import React, {
  useCallback,
  useMemo,
  useRef,
  useState,
  StrictMode,
} from "react";
import { createRoot } from "react-dom/client";
import { AgGridReact, AgGridProvider } from "ag-grid-react";
import "./styles.css";
import {
  ClientSideRowModelModule,
  ColDef,
  ColGroupDef,
  GridApi,
  GridOptions,
  LoadingRowsOptions,
  ModuleRegistry,
  enableDevValidations,
} from "ag-grid-community";

if (process.env.NODE_ENV !== "production") {
  enableDevValidations();
}

const modules = [ClientSideRowModelModule];

interface IAthlete {
  athlete: string;
  country: string;
  sport: string;
  year: number;
  gold: number;
  silver: number;
  bronze: number;
}

const GridExample = () => {
  const gridRef = useRef<AgGridReact<IAthlete>>(null);
  const containerStyle = useMemo(() => ({ width: "100%", height: "100%" }), []);
  const gridStyle = useMemo(() => ({ height: "100%", width: "100%" }), []);
  const [rowData, setRowData] = useState<IAthlete[]>([
    {
      athlete: "Michael Phelps",
      country: "United States",
      sport: "Swimming",
      year: 2008,
      gold: 8,
      silver: 0,
      bronze: 0,
    },
    {
      athlete: "Natalie Coughlin",
      country: "United States",
      sport: "Swimming",
      year: 2008,
      gold: 1,
      silver: 2,
      bronze: 3,
    },
    {
      athlete: "Aleksey Nemov",
      country: "Russia",
      sport: "Gymnastics",
      year: 2000,
      gold: 2,
      silver: 1,
      bronze: 3,
    },
    {
      athlete: "Alicia Coutts",
      country: "Australia",
      sport: "Swimming",
      year: 2012,
      gold: 1,
      silver: 3,
      bronze: 1,
    },
    {
      athlete: "Missy Franklin",
      country: "United States",
      sport: "Swimming",
      year: 2012,
      gold: 4,
      silver: 0,
      bronze: 1,
    },
    {
      athlete: "Ryan Lochte",
      country: "United States",
      sport: "Swimming",
      year: 2012,
      gold: 2,
      silver: 2,
      bronze: 1,
    },
    {
      athlete: "Chris Hoy",
      country: "Great Britain",
      sport: "Cycling",
      year: 2008,
      gold: 3,
      silver: 0,
      bronze: 0,
    },
    {
      athlete: "Ian Thorpe",
      country: "Australia",
      sport: "Swimming",
      year: 2000,
      gold: 3,
      silver: 2,
      bronze: 0,
    },
  ]);
  const loadingRows = useMemo<boolean | LoadingRowsOptions>(() => {
    return { rowCount: 10 };
  }, []);
  const [columnDefs, setColumnDefs] = useState<ColDef[]>([
    { field: "athlete" },
    { field: "country" },
    { field: "sport" },
    { field: "year" },
    { field: "gold" },
    { field: "silver" },
    { field: "bronze" },
  ]);

  const onLoadingToggled = useCallback(() => {
    const loading =
      document.querySelector<HTMLInputElement>("#loading-toggle")!.checked;
    gridRef.current!.api.setGridOption("loading", loading);
  }, []);

  const onRowCountChanged = useCallback(() => {
    const rowCount =
      document.querySelector<HTMLInputElement>("#row-count")!.valueAsNumber;
    if (!Number.isInteger(rowCount) || rowCount < 1) {
      return;
    }
    gridRef.current!.api.setGridOption("loadingRows", { rowCount });
  }, []);

  return (
    <AgGridProvider modules={modules}>
      <div style={containerStyle}>
        <div className="example-wrapper">
          <div className="example-header">
            <label>
              <span>loading:</span>
              <input
                type="checkbox"
                id="loading-toggle"
                defaultChecked
                onChange={onLoadingToggled}
              />
            </label>
            <label>
              <span>loadingRows.rowCount:</span>
              <input
                type="number"
                id="row-count"
                min="1"
                max="50"
                defaultValue="10"
                onChange={onRowCountChanged}
              />
            </label>
          </div>

          <div style={gridStyle}>
            <AgGridReact<IAthlete>
              ref={gridRef}
              rowData={rowData}
              loading={true}
              loadingRows={loadingRows}
              columnDefs={columnDefs}
            />
          </div>
        </div>
      </div>
    </AgGridProvider>
  );
};

const root = createRoot(document.getElementById("root")!);
root.render(
  <StrictMode>
    <GridExample />
  </StrictMode>,
);
```

[Live example: Loading Rows](https://www.ag-grid.com/examples/loading-rows/client-side-loading-rows/reactFunctionalTs/)

> **Note**
>
> For loading rows managed by a server-side datasource, see [Server-Side Row Model Loading Rows](https://www.ag-grid.com/react-data-grid/server-side-model-loading-rows/).

## Enabling Loading Rows

Set `loadingRows=true` to use skeleton rows when `loading=true`. Ten rows are displayed by default. Alternatively, provide `LoadingRowsOptions` with `rowCount` to configure the number displayed.

```jsx
const loading = true;
const loadingRows = {
    rowCount: 10,
};

<AgGridReact
    loading={loading}
    loadingRows={loadingRows}
/>
```

| Property | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `loading` | `boolean` |  |  |  |
| `loadingRows` | `boolean \| LoadingRowsOptions` |  |  |  |

Loading rows are visual placeholders and are not included in Client-Side Row Model operations such as sorting, filtering, grouping or selection. When loading finishes, set `loading=false` to display the row data.

Both options can be updated at runtime. Update `loadingRows` to change the row count while loading, or set it to `false` to switch back to the overlay without ending the loading state.

## Custom Loading Cells

Set `loadingCellRenderer` and `loadingCellRendererParams` on a column definition to customise that column, or on `defaultColDef` to customise every loading cell. See [Loading Cell Component](https://www.ag-grid.com/react-data-grid/component-loading-cell-renderer/) for component interfaces, parameters and dynamic component selection.

The following example uses a custom loading component for the Athlete column while the other columns retain the default skeleton effect.

#### Custom Loading Cells

```tsx
"use client";

import React, {
  useCallback,
  useMemo,
  useRef,
  useState,
  StrictMode,
} from "react";
import { createRoot } from "react-dom/client";
import { AgGridReact, AgGridProvider } from "ag-grid-react";
import "./styles.css";
import {
  ClientSideRowModelModule,
  ColDef,
  ColGroupDef,
  GridApi,
  GridOptions,
  LoadingRowsOptions,
  ModuleRegistry,
  enableDevValidations,
} from "ag-grid-community";
import CustomLoadingCellRenderer from "./customLoadingCellRenderer.tsx";

if (process.env.NODE_ENV !== "production") {
  enableDevValidations();
}

const modules = [ClientSideRowModelModule];

interface IAthlete {
  athlete: string;
  country: string;
  sport: string;
  year: number;
  gold: number;
  silver: number;
  bronze: number;
}

const GridExample = () => {
  const gridRef = useRef<AgGridReact<IAthlete>>(null);
  const containerStyle = useMemo(() => ({ width: "100%", height: "100%" }), []);
  const gridStyle = useMemo(() => ({ height: "100%", width: "100%" }), []);
  const [rowData, setRowData] = useState<IAthlete[]>([
    {
      athlete: "Michael Phelps",
      country: "United States",
      sport: "Swimming",
      year: 2008,
      gold: 8,
      silver: 0,
      bronze: 0,
    },
    {
      athlete: "Natalie Coughlin",
      country: "United States",
      sport: "Swimming",
      year: 2008,
      gold: 1,
      silver: 2,
      bronze: 3,
    },
    {
      athlete: "Aleksey Nemov",
      country: "Russia",
      sport: "Gymnastics",
      year: 2000,
      gold: 2,
      silver: 1,
      bronze: 3,
    },
    {
      athlete: "Alicia Coutts",
      country: "Australia",
      sport: "Swimming",
      year: 2012,
      gold: 1,
      silver: 3,
      bronze: 1,
    },
    {
      athlete: "Missy Franklin",
      country: "United States",
      sport: "Swimming",
      year: 2012,
      gold: 4,
      silver: 0,
      bronze: 1,
    },
    {
      athlete: "Ryan Lochte",
      country: "United States",
      sport: "Swimming",
      year: 2012,
      gold: 2,
      silver: 2,
      bronze: 1,
    },
    {
      athlete: "Chris Hoy",
      country: "Great Britain",
      sport: "Cycling",
      year: 2008,
      gold: 3,
      silver: 0,
      bronze: 0,
    },
    {
      athlete: "Ian Thorpe",
      country: "Australia",
      sport: "Swimming",
      year: 2000,
      gold: 3,
      silver: 2,
      bronze: 0,
    },
  ]);
  const loadingRows = useMemo<boolean | LoadingRowsOptions>(() => {
    return { rowCount: 10 };
  }, []);
  const [columnDefs, setColumnDefs] = useState<ColDef[]>([
    {
      field: "athlete",
      loadingCellRenderer: CustomLoadingCellRenderer,
      loadingCellRendererParams: {
        loadingMessage: "Loading athletes...",
      },
    },
    { field: "country" },
    { field: "sport" },
    { field: "year" },
    { field: "gold" },
    { field: "silver" },
    { field: "bronze" },
  ]);

  const onLoadingToggled = useCallback(() => {
    const loading =
      document.querySelector<HTMLInputElement>("#loading-toggle")!.checked;
    gridRef.current!.api.setGridOption("loading", loading);
  }, []);

  return (
    <AgGridProvider modules={modules}>
      <div style={containerStyle}>
        <div className="example-wrapper">
          <div className="example-header">
            <label>
              <span>loading:</span>
              <input
                type="checkbox"
                id="loading-toggle"
                defaultChecked
                onChange={onLoadingToggled}
              />
            </label>
          </div>

          <div style={gridStyle}>
            <AgGridReact<IAthlete>
              ref={gridRef}
              rowData={rowData}
              loading={true}
              loadingRows={loadingRows}
              columnDefs={columnDefs}
            />
          </div>
        </div>
      </div>
    </AgGridProvider>
  );
};

const root = createRoot(document.getElementById("root")!);
root.render(
  <StrictMode>
    <GridExample />
  </StrictMode>,
);
```

[Live example: Custom Loading Cells](https://www.ag-grid.com/examples/loading-rows/custom-loading-cells/reactFunctionalTs/)
