---
title: "Context"
framework: react
version: "36.1.0"
---

# Context

This sections covers how shared contextual information can be passed around the grid.

## Overview

The context object is passed to all callbacks and events used in the grid. The purpose of the context object is to allow the client application to pass details to custom callbacks such as the [Cell Renderers](https://www.ag-grid.com/react-data-grid/component-cell-renderer/) and [Cell Editors](https://www.ag-grid.com/react-data-grid/cell-editing/).

| Property | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `context` | `any` |  |  | Provides a context object that is provided to different callbacks the grid uses. Used for passing additional information to the callbacks used by your application. [Initial](https://www.ag-grid.com/react-data-grid/grid-interface/#initial-grid-options). |

To update the context call `api.setGridOption` with the new context. Alternatively, if you maintain a reference to the context object it's values can be mutated directly.

## Context Object Example

The example below demonstrates how the context object can be used. Note the following:

- Selecting the reporting currency from the dropdown places it in the context object.
- When the reporting currency is changed the cell renderer uses the currency supplied in the context object to calculate the value using: `params.context.reportingCurrency`.
- The price column header is updated to show the selected currency using a header value getter using `ctx.reportingCurrency`.

#### Context Object

```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 {
  ClientSideRowModelModule,
  ColDef,
  ColGroupDef,
  GridApi,
  GridOptions,
  HighlightChangesModule,
  ICellRendererParams,
  ModuleRegistry,
  RenderApiModule,
  ValueGetterParams,
  enableDevValidations,
} from "ag-grid-community";

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

const modules = [
  RenderApiModule,
  HighlightChangesModule,
  ClientSideRowModelModule,
];

const gbpFormatter = new Intl.NumberFormat("en-US", {
  style: "currency",
  currency: "GBP",
  minimumFractionDigits: 2,
});

const eurFormatter = new Intl.NumberFormat("en-US", {
  style: "currency",
  currency: "EUR",
  minimumFractionDigits: 2,
});

const usdFormatter = new Intl.NumberFormat("en-US", {
  style: "currency",
  currency: "USD",
  minimumFractionDigits: 2,
});

const currencyComparator = (a: any, b: any) => {
  return a.amount - b.amount;
};

const currencyCellRenderer = (params: ICellRendererParams) => {
  switch (params.value.currency) {
    case "EUR":
      return eurFormatter.format(params.value.amount);
    case "USD":
      return usdFormatter.format(params.value.amount);
    case "GBP":
      return gbpFormatter.format(params.value.amount);
  }
  return params.value.amount;
};

function reportingCurrencyValueGetter(params: ValueGetterParams) {
  // Rates taken from google at time of writing
  const exchangeRates: Record<string, any> = {
    EUR: {
      GBP: 0.72,
      USD: 1.08,
    },
    GBP: {
      EUR: 1.29,
      USD: 1.5,
    },
    USD: {
      GBP: 0.67,
      EUR: 0.93,
    },
  };
  const price = params.data[params.colDef.field!];
  const reportingCurrency = params.context.reportingCurrency;
  const fxRateSet = exchangeRates[reportingCurrency];
  const fxRate = fxRateSet[price.currency];
  let priceInReportingCurrency;
  if (fxRate) {
    priceInReportingCurrency = price.amount * fxRate;
  } else {
    priceInReportingCurrency = price.amount;
  }
  const result = {
    currency: reportingCurrency,
    amount: priceInReportingCurrency,
  };
  return result;
}

function getData() {
  return [
    { product: "Product 1", price: { currency: "EUR", amount: 644 } },
    { product: "Product 2", price: { currency: "EUR", amount: 354 } },
    { product: "Product 3", price: { currency: "GBP", amount: 429 } },
    { product: "Product 4", price: { currency: "GBP", amount: 143 } },
    { product: "Product 5", price: { currency: "USD", amount: 345 } },
    { product: "Product 6", price: { currency: "USD", amount: 982 } },
  ];
}

const GridExample = () => {
  const gridRef = useRef<AgGridReact>(null);
  const containerStyle = useMemo(() => ({ width: "100%", height: "100%" }), []);
  const gridStyle = useMemo(() => ({ height: "90%", width: "100%" }), []);
  const [rowData, setRowData] = useState<any[]>(getData());
  const [columnDefs, setColumnDefs] = useState<ColDef[]>([
    { field: "product" },
    { headerName: "Currency", field: "price.currency" },
    {
      headerName: "Price Local",
      field: "price",
      cellRenderer: currencyCellRenderer,
      comparator: currencyComparator,
      cellDataType: false,
    },
    {
      headerName: "Report Price",
      field: "price",
      cellRenderer: currencyCellRenderer,
      comparator: currencyComparator,
      valueGetter: reportingCurrencyValueGetter,
      headerValueGetter: "ctx.reportingCurrency",
    },
  ]);
  const defaultColDef = useMemo<ColDef>(() => {
    return {
      flex: 1,
      enableCellChangeFlash: true,
    };
  }, []);
  const context = useMemo<any>(() => {
    return {
      reportingCurrency: "EUR",
    };
  }, []);

  const currencyChanged = useCallback(() => {
    const value = (document.getElementById("currency") as any).value;
    gridRef.current!.api.setGridOption("context", { reportingCurrency: value });
    gridRef.current!.api.refreshCells();
    gridRef.current!.api.refreshHeader();
  }, []);

  return (
    <AgGridProvider modules={modules}>
      <div style={containerStyle}>
        <div style={{ height: "10%" }}>
          <select id="currency" onChange={currencyChanged}>
            <option value="EUR">EUR</option>
            <option value="GBP">GBP</option>
            <option value="USD">USD</option>
          </select>
        </div>

        <div style={gridStyle}>
          <AgGridReact
            ref={gridRef}
            rowData={rowData}
            columnDefs={columnDefs}
            defaultColDef={defaultColDef}
            context={context}
          />
        </div>
      </div>
    </AgGridProvider>
  );
};

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

[Live example: Context Object](https://www.ag-grid.com/examples/context/context/reactFunctionalTs)

## Context & Expressions Example

Below shows a complex example making use of value getters (using expressions) and class rules (again using expressions). The grid shows 'actual vs budget data and yearly total' for widget sales split by city and country.

- The **Location** column is showing the aggregation groups, grouping by city and country.
- The **Monthly Data** columns are affected by the context. Depending on the selected period, the data displayed is either actual (`x_act`) or budgeted (`x_bud`) data for the month (eg. `jan_act` when Jan is green, or `jan_bud` when Jan is red). Similarly, the background color is also changed using class rules dependent on the selected period.
- **sum(YTD)** is the total of the 'actual' figures, i.e. adding up all the green. This also changes as the period is changed.

Notice that the example (including calculating the expression on the fly, the grid only calculates what's needed to be displayed) runs very fast (once the data is loaded) despite having over 6,000 rows.

This example is best viewed by opening it in a new tab.

#### Monthly Sales

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

import type {
  ColDef,
  ColGroupDef,
  RowSelectionOptions,
} from "ag-grid-community";
import {
  CellStyleModule,
  ClientSideRowModelApiModule,
  ClientSideRowModelModule,
  QuickFilterModule,
  RenderApiModule,
  RowSelectionModule,
  enableDevValidations,
} from "ag-grid-community";
import {
  FiltersToolPanelModule,
  RowGroupingModule,
  SetFilterModule,
} from "ag-grid-enterprise";
import type { CustomCellRendererProps } from "ag-grid-react";
import { AgGridProvider, AgGridReact } from "ag-grid-react";

import "./styles.css";

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

const modules = [
  ClientSideRowModelApiModule,
  RenderApiModule,
  RowSelectionModule,
  CellStyleModule,
  QuickFilterModule,
  ClientSideRowModelModule,
  RowGroupingModule,
  SetFilterModule,
  FiltersToolPanelModule,
];

const monthValueGetter =
  '(ctx.month < ctx.months.indexOf(colDef.field)) ? data[colDef.field + "_bud"] : data[colDef.field + "_act"]';

const monthCellClassRules = {
  "cell-act": "ctx.month < ctx.months.indexOf(colDef.field)",
  "cell-bud": "ctx.month >= ctx.months.indexOf(colDef.field)",
  "cell-negative": "x < 0",
};

const yearToDateValueGetter =
  'var total = 0; ctx.months.forEach( function(monthName, monthIndex) { if (monthIndex<=ctx.month) { total += data[monthName + "_act"]; } }); return total; ';

const accountingCellRenderer = function (params: CustomCellRendererProps) {
  if (params.value == null) {
    return "";
  } else if (params.value >= 0) {
    return params.value.toLocaleString();
  } else {
    return "(" + Math.abs(params.value).toLocaleString() + ")";
  }
};

const monthNames = [
  "Budget Only",
  "Year to Jan",
  "Year to Feb",
  "Year to Mar",
  "Year to Apr",
  "Year to May",
  "Year to Jun",
  "Year to Jul",
  "Year to Aug",
  "Year to Sep",
  "Year to Oct",
  "Year to Nov",
  "Full Year",
];

const rowSelection: RowSelectionOptions = {
  mode: "multiRow",
  headerCheckbox: false,
  groupSelects: "descendants",
};

const GridExample = () => {
  const gridRef = useRef<AgGridReact>(null);
  const containerStyle = useMemo(() => ({ width: "100%", height: "100%" }), []);
  const gridStyle = useMemo(() => ({ height: "100%", width: "100%" }), []);

  const [columnDefs, setColumnDefs] = useState<(ColDef | ColGroupDef)[]>([
    {
      field: "country",
      rowGroup: true,
      hide: true,
    },
    {
      headerName: "Monthly Data",
      children: [
        {
          field: "jan",
          cellRenderer: accountingCellRenderer,
          cellClass: "cell-figure",
          valueGetter: monthValueGetter,
          cellClassRules: monthCellClassRules,
          aggFunc: "sum",
        },
        {
          field: "feb",
          cellRenderer: accountingCellRenderer,
          cellClass: "cell-figure",
          valueGetter: monthValueGetter,
          cellClassRules: monthCellClassRules,
          aggFunc: "sum",
        },
        {
          field: "mar",
          cellRenderer: accountingCellRenderer,
          cellClass: "cell-figure",
          valueGetter: monthValueGetter,
          cellClassRules: monthCellClassRules,
          aggFunc: "sum",
        },
        {
          field: "apr",
          cellRenderer: accountingCellRenderer,
          cellClass: "cell-figure",
          valueGetter: monthValueGetter,
          cellClassRules: monthCellClassRules,
          aggFunc: "sum",
        },
        {
          field: "may",
          cellRenderer: accountingCellRenderer,
          cellClass: "cell-figure",
          valueGetter: monthValueGetter,
          cellClassRules: monthCellClassRules,
          aggFunc: "sum",
        },
        {
          field: "jun",
          cellRenderer: accountingCellRenderer,
          cellClass: "cell-figure",
          valueGetter: monthValueGetter,
          cellClassRules: monthCellClassRules,
          aggFunc: "sum",
        },
        {
          headerName: "YTD",
          cellClass: "cell-figure",
          cellRenderer: accountingCellRenderer,
          valueGetter: yearToDateValueGetter,
          aggFunc: "sum",
        },
      ],
    },
  ]);
  const context = useRef<{ month: number; months: string[] }>({
    month: 0,
    months: [
      "jan",
      "feb",
      "mar",
      "apr",
      "may",
      "jun",
      "jul",
      "aug",
      "sep",
      "oct",
      "nov",
      "dec",
    ],
  });
  const defaultColDef = useMemo<ColDef>(() => {
    return {
      flex: 1,
      minWidth: 120,
    };
  }, []);
  const autoGroupColumnDef = useMemo<ColDef>(() => {
    return {
      headerName: "Location",
      field: "city",
      minWidth: 260,
      cellRenderer: "agGroupCellRenderer",
    };
  }, []);

  const { data, loading } = useFetchJson(
    "https://www.ag-grid.com/example-assets/monthly-sales.json",
  );

  const onChangeMonth = useCallback(
    (i: number) => {
      let newMonth = (context.current.month += i);
      if (newMonth < -1) {
        newMonth = -1;
      }
      if (newMonth > 5) {
        newMonth = 5;
      }
      // Mutate the context object in place
      context.current.month = newMonth;
      document.querySelector("#monthName")!.textContent =
        monthNames[newMonth + 1];
      gridRef.current!.api.refreshClientSideRowModel("aggregate");
      gridRef.current!.api.refreshCells();
    },
    [monthNames],
  );

  const onQuickFilterChanged = useCallback((value: string) => {
    gridRef.current!.api.setGridOption("quickFilterText", value);
  }, []);

  return (
    <AgGridProvider modules={modules}>
      <div style={containerStyle}>
        <div className="test-container">
          <div className="test-header">
            <input
              type="text"
              id="filter-text-box"
              style={{ width: "100px" }}
              onChange={(e) => onQuickFilterChanged(e.target.value)}
              placeholder="Filter..."
            />

            <span style={{ paddingLeft: "20px" }}>
              <b>Period:</b>
              <button onClick={() => onChangeMonth(-1)}>
                <i className="fa fa-chevron-left"></i>
              </button>
              <button onClick={() => onChangeMonth(1)}>
                <i className="fa fa-chevron-right"></i>
              </button>
              <span
                id="monthName"
                style={{ width: "100px", display: "inline-block" }}
              >
                Year to Jan
              </span>
            </span>

            <span style={{ paddingLeft: "20px" }}>
              <b>Legend:</b>&nbsp;&nbsp;
              <div className="cell-bud legend-box"></div> Actual&nbsp;&nbsp;
              <div className="cell-act legend-box"></div> Budget
            </span>
          </div>

          <div style={gridStyle}>
            <AgGridReact
              ref={gridRef}
              rowData={data}
              loading={loading}
              columnDefs={columnDefs}
              suppressMovableColumns={true}
              context={context.current}
              defaultColDef={defaultColDef}
              autoGroupColumnDef={autoGroupColumnDef}
              rowSelection={rowSelection}
            />
          </div>
        </div>
      </div>
    </AgGridProvider>
  );
};

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

[Live example: Monthly Sales](https://www.ag-grid.com/examples/context/monthly-sales/reactFunctionalTs)
