---
title: "Grid Lifecycle"
framework: react
version: "36.1.0"
---

# Grid Lifecycle

This section covers some common lifecycle events that are raised after grid initialisation, data updates, and before the grid is destroyed.

> **Note**
>
> The events on this page are listed in the order they are raised.

## Grid Ready

The `gridReady` event fires upon grid initialisation but the grid may not be fully rendered.

**Common Uses**

- Customising Grid via API calls.
- Event listener setup.
- Grid-dependent setup code.

In this example, `gridReady` applies user pinning preferences before rendering data.

#### Using Grid Ready Event

```tsx
'use client';
import React, {
  StrictMode,
  useCallback,
  useMemo,
  useRef,
  useState,
} from "react";
import { createRoot } from "react-dom/client";

import type { ColDef, GridReadyEvent } from "ag-grid-community";
import {
  ClientSideRowModelModule,
  ColumnApiModule,
  enableDevValidations,
} from "ag-grid-community";
import { AgGridProvider, AgGridReact } from "ag-grid-react";

import { getData } from "./data";
import "./styles.css";

// Enable extended validations only for development
if (process.env.NODE_ENV !== "production") {
  enableDevValidations();
}

const modules = [ColumnApiModule, ClientSideRowModelModule];

const GridExample = () => {
  const gridRef = useRef<AgGridReact>(null);
  const [gridKey, setGridKey] = useState<string>(`grid-key-${window.agRandom()}`);
  const containerStyle = useMemo(() => ({ width: "100%", height: "100%" }), []);
  const gridStyle = useMemo(() => ({ height: "100%", width: "100%" }), []);
  const [rowData, setRowData] = useState<any[]>(getData());

  const [columnDefs, setColumnDefs] = useState<ColDef[]>([
    { field: "name", headerName: "Athlete", width: 250 },
    { field: "person.country", headerName: "Country" },
    { field: "person.age", headerName: "Age" },
    { field: "medals.gold", headerName: "Gold Medals" },
    { field: "medals.silver", headerName: "Silver Medals" },
    { field: "medals.bronze", headerName: "Bronze Medals" },
  ]);

  const onGridReady = useCallback((params: GridReadyEvent) => {
    const checkbox = document.querySelector<HTMLInputElement>(
      "#pinFirstColumnOnLoad",
    )!;
    const shouldPinFirstColumn = checkbox && checkbox.checked;
    if (shouldPinFirstColumn) {
      params.api.applyColumnState({
        state: [{ colId: "name", pinned: "left" }],
      });
    }
  }, []);

  const reloadGrid = useCallback(() => {
    // Trigger re-load by assigning a new key to the Grid React component
    setGridKey(`grid-key-${window.agRandom()}`);
  }, []);

  return (
    <AgGridProvider modules={modules}>
      <div style={containerStyle}>
        <div className="test-container">
          <div className="test-header">
            <div style={{ marginBottom: "1rem" }}>
              <input type="checkbox" id="pinFirstColumnOnLoad" />
              <label htmlFor="pinFirstColumnOnLoad">
                Pin first column on load
              </label>
            </div>

            <div style={{ marginBottom: "1rem" }}>
              <button id="reloadGridButton" onClick={reloadGrid}>
                Reload Grid
              </button>
            </div>
          </div>

          <div style={gridStyle}>
            <AgGridReact
              key={gridKey}
              ref={gridRef}
              rowData={rowData}
              columnDefs={columnDefs}
              onGridReady={onGridReady}
            />
          </div>
        </div>
      </div>
    </AgGridProvider>
  );
};

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

[Live example: Using Grid Ready Event](https://www.ag-grid.com/examples/grid-lifecycle/grid-ready/reactFunctionalTs)

## First Data Rendered

The `firstDataRendered` event fires the first time data is rendered into the grid. It will only be fired once unlike `rowDataUpdated` which is fired on every data change.

## Row Data Updated

The `rowDataUpdated` event fires every time the grid's data changes, by [Updating Row Data](https://www.ag-grid.com/react-data-grid/data-update-row-data/) or by applying [Transaction Updates](https://www.ag-grid.com/react-data-grid/data-update-transactions/). In the [Server Side Row Model](https://www.ag-grid.com/react-data-grid/server-side-model/), use the [Model Updated Event](https://www.ag-grid.com/react-data-grid/grid-events/#reference-gridLifecycle-modelUpdated) instead.

In this example the time at which `firstDataRendered` and `rowDataUpdated` are fired is recorded above the grid. Note that `firstDataRendered` is only set on the initial load of the grid and is not updated when reloading data.

#### Using Row Data Event

```tsx
'use client';
import React, { StrictMode, useCallback, useEffect, useState } from "react";
import { createRoot } from "react-dom/client";

import {
  ClientSideRowModelModule,
  enableDevValidations,
} from "ag-grid-community";
import type {
  FirstDataRenderedEvent,
  RowDataUpdatedEvent,
} from "ag-grid-community";
import { AgGridProvider, AgGridReact } from "ag-grid-react";

import { fetchDataAsync } from "./data";
import type { TAthlete } from "./data";
import "./styles.css";

// Enable extended validations only for development
if (process.env.NODE_ENV !== "production") {
  enableDevValidations();
}

const modules = [ClientSideRowModelModule];

const updateRowCount = (id: string) => {
  const element = document.querySelector(`#${id} > .value`);
  element!.textContent = `${new Date().toLocaleTimeString()}`;
};

const columnDefs = [
  { field: "name", headerName: "Athlete" },
  { field: "person.age", headerName: "Age" },
  { field: "medals.gold", headerName: "Gold Medals" },
];

const GridExample = () => {
  const [loading, setLoading] = useState<boolean>(true);
  const [rowData, setRowData] = useState<TAthlete[] | undefined>();

  const onFirstDataRendered = useCallback((event: FirstDataRenderedEvent) => {
    updateRowCount("firstDataRendered");
    console.log("First Data Rendered");
  }, []);

  const onRowDataUpdated = useCallback(
    (event: RowDataUpdatedEvent<TAthlete>) => {
      updateRowCount("rowDataUpdated");
      console.log("Row Data Updated");
    },
    [],
  );

  const reloadData = useCallback(() => {
    console.log("Loading Data ...");
    setLoading(true);
    fetchDataAsync()
      .then((data) => {
        console.info("Data Loaded");
        setRowData(data);
      })
      .catch((error) => {
        console.error("Failed to load data", error);
      })
      .finally(() => {
        setLoading(false);
      });
  }, []);

  useEffect(reloadData, []);

  return (
    <AgGridProvider modules={modules}>
      <div className="test-container">
        <div className="test-header">
          <div id="firstDataRendered">
            First Data Rendered: <span className="value">-</span>
          </div>
          <div id="rowDataUpdated">
            Row Data Updated: <span className="value">-</span>
          </div>
          <div>
            <button disabled={loading} onClick={reloadData}>
              Reload Data
            </button>
          </div>
        </div>

        <div style={{ height: "100%" }}>
          <AgGridReact
            loading={loading}
            rowData={rowData}
            columnDefs={columnDefs}
            onFirstDataRendered={onFirstDataRendered}
            onRowDataUpdated={onRowDataUpdated}
          />
        </div>
      </div>
    </AgGridProvider>
  );
};

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

[Live example: Using Row Data Event](https://www.ag-grid.com/examples/grid-lifecycle/row-data-updated/reactFunctionalTs)

## Grid Pre-Destroyed

The `gridPreDestroyed` event fires just before the grid is destroyed and is removed from the DOM.

**Common Uses**

- Clean up resources.
- Save grid state.
- Disconnect other libraries.

The [Grid State Example](https://www.ag-grid.com/react-data-grid/grid-state/#saving-and-restoring-state) demonstrates how `gridPreDestroyed` can be used to save and restore grid state.
