---
title: "Asynchronous Data"
enterprise: true
framework: react
version: "14.1.0"
---

# Asynchronous Data

Asynchronous Data allows charts to load data on demand, supporting progressive detail loading and server-side paging when used with [Zoom](https://www.ag-grid.com/charts/react/zoom/) or the [Scrollbar](https://www.ag-grid.com/charts/react/scrollbar/).

## Data Source

Use the `dataSource` option to provide an asynchronous `getData` callback. The chart calls this function on initial load and then whenever the visible window changes, and displays a loading overlay until the returned promise resolves.

#### Async Data

```tsx
import React, { useState, useRef, Fragment } from "react";
import { createRoot } from "react-dom/client";
import { AgCharts } from "ag-charts-react";
import {
  AgCartesianChartOptions,
  AgChartsInstance,
  AnimationModule,
  ContextMenuModule,
  CrosshairModule,
  DataSourceModule,
  LegendModule,
  LineSeriesModule,
  ModuleRegistry,
  NavigatorModule,
  NumberAxisModule,
  TimeAxisModule,
  ZoomModule,
} from "ag-charts-enterprise";
import { Database } from "./data";
import { FakeServer } from "./fakeServer";
import clone from "clone";

ModuleRegistry.registerModules([
  AnimationModule,
  CrosshairModule,
  DataSourceModule,
  LegendModule,
  LineSeriesModule,
  NavigatorModule,
  NumberAxisModule,
  TimeAxisModule,
  ZoomModule,
  ContextMenuModule,
]);

const ChartExample = () => {
  const chartRef = useRef<AgChartsInstance>(null);
  const [options, setOptions] = useState<AgCartesianChartOptions>({
    dataSource: {
      getData: ({ windowStart, windowEnd, source }) => {
        // Request the data from the server, this is an asynchronous call which may take up to 2500ms. In your
        // application, replace this with a call to your server api.
        // The navigator mini chartRef.current! requests a coarse, full-range overview; the main chartRef.current! requests the visible
        // window, and the server returns higher-resolution data as the window narrows.
        return source === "mini-chart"
          ? FakeServer.get({})
          : FakeServer.get({ windowStart, windowEnd });
      },
    },
    navigator: {
      enabled: true,
      miniChart: {},
    },
    zoom: {
      enabled: true,
    },
    initialState: {
      zoom: {
        ratioX: { start: 0.7, end: 1 },
      },
    },
    series: [
      {
        type: "line",
        xKey: "time",
        yKey: "price",
        yName: "Price",
      },
    ],
    axes: {
      y: {
        type: "number",
        min: 400,
        max: 1600,
      },
      x: {
        type: "time",
        min: new Date("2019-01-01 00:00:00"),
        max: new Date("2024-12-30 23:59:59"),
        interval: {
          minSpacing: 100,
          maxSpacing: 200,
        },
        label: {
          formatter: ({ value }) =>
            Intl.DateTimeFormat("en-GB", {
              day: "2-digit",
              month: "short",
              year: "2-digit",
            }).format(new Date(value)),
        },
      },
    },
  });

  // Refresh the underlying server data, then call updateDelta({}) to re-trigger getData for the
  // current window. The chartRef.current! shows its loading overlay while the new data is fetched.
  const reload = () => {
    Database.refresh();
    chartRef.current!.updateDelta({});
  };

  return (
    <Fragment>
      <div className="example-controls">
        <div className="controls-row">
          <button onClick={reload}>Reload Data</button>
        </div>
      </div>
      <AgCharts ref={chartRef} options={options} />
    </Fragment>
  );
};

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

[Live example: Async Data](https://www.ag-grid.com/charts/reactFunctionalTs/async-data/examples/async-data)

```js
{
    dataSource: {
        getData: ({ windowStart, windowEnd }) => {
            return FakeServer.get({ windowStart, windowEnd });
        },
    },
}
```

In this example:

- The fake server returns coarse data covering the full date range alongside finer-grained data for the visible window.
- As the user zooms in, `getData` is re-invoked with updated `windowStart` and `windowEnd` values and the server returns higher-resolution data for that range.

The `getData` callback receives an `AgDataSourceCallbackParams` object with:

- `windowStart`: the start of the visible window.
- `windowEnd`: the end of the visible window.
- `source`: what triggered the request, such as `'mini-chart'`, `'user-interaction'` or `'chart-update'`.
- `context`: the [chart context object](https://www.ag-grid.com/charts/react/context/), if one has been provided.

> **Note**
>
> The returned data must include the first and last data points so the chart can establish the axis domain, unless the axis has explicit `min` and `max` values.

When the [Navigator Mini Chart](https://www.ag-grid.com/charts/react/navigator#mini-chart) is enabled, it issues its own `getData` call with `source: 'mini-chart'` to load a full-range overview, independent of the main chart's windowed fetches. This is only done on initial load or options update.

### Triggering a Reload

Calling `updateDelta({})` with an empty object triggers `getData` to be called again, which is useful for refreshing data on demand. The **Reload Data** button in the example above does exactly this; the loading overlay is shown while the request is in progress, and the chart updates with the freshly fetched data once it resolves.

```js
chart.updateDelta({});
```

## Loading Overlay

While `getData` is in progress, the chart displays a [Loading Overlay](https://www.ag-grid.com/charts/react/overlays/#loading-data-overlay) automatically. The overlay can be customised through the `overlays.loading` option; see [Overlays](https://www.ag-grid.com/charts/react/overlays/) for text customisation and custom renderers.

### Manual Control

Set `loading` on the chart options to control the overlay independently of `dataSource`.

#### Loading Overlay

```tsx
import React, { useState, useRef, Fragment } from "react";
import { createRoot } from "react-dom/client";
import { AgCharts } from "ag-charts-react";
import {
  AgChartOptions,
  AgChartsInstance,
  AnimationModule,
  ContextMenuModule,
  CrosshairModule,
  DataSourceModule,
  LegendModule,
  LineSeriesModule,
  ModuleRegistry,
  NumberAxisModule,
} from "ag-charts-enterprise";
import clone from "clone";

const datasets = [
  [120, 145, 98, 160, 135],
  [200, 175, 220, 190, 210],
  [80, 95, 70, 110, 85],
  [155, 130, 180, 145, 165],
];
let loadIndex = 0;
function getData() {
  const values = datasets[loadIndex % datasets.length];
  loadIndex++;
  return values.map((spending, i) => ({ year: 2020 + i, spending }));
}
ModuleRegistry.registerModules([
  AnimationModule,
  CrosshairModule,
  DataSourceModule,
  LegendModule,
  LineSeriesModule,
  NumberAxisModule,
  ContextMenuModule,
]);

const ChartExample = () => {
  const chartRef = useRef<AgChartsInstance>(null);
  const [options, setOptions] = useState<AgChartOptions>({
    dataSource: {
      getData: () =>
        new Promise((resolve) => setTimeout(() => resolve(getData()), 2000)),
    },
    series: [
      {
        type: "line",
        xKey: "year",
        yKey: "spending",
      },
    ],
    axes: {
      x: { type: "number", title: { text: "Year" } },
      y: { type: "number", title: { text: "Spending" } },
    },
  });

  const setLoading = (value: boolean | undefined) => {
    chartRef.current!.updateDelta({ loading: value });
  };

  const reload = () => {
    chartRef.current!.updateDelta({});
  };

  return (
    <Fragment>
      <div className="example-controls">
        <div className="controls-row">
          Loading:
          <button onClick={() => setLoading(true)}>
            <code>true</code>
          </button>
          <button onClick={() => setLoading(false)}>
            <code>false</code>
          </button>
          <button onClick={() => setLoading(undefined)}>
            <code>undefined</code>
          </button>
        </div>
        <div className="controls-row">
          <button onClick={reload}>Reload</button>
        </div>
      </div>
      <AgCharts ref={chartRef} options={options} />
    </Fragment>
  );
};

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

[Live example: Loading Overlay](https://www.ag-grid.com/charts/reactFunctionalTs/async-data/examples/loading)

Use the buttons to override the loading state.

```js
{
    loading: true,
}
```

- `true` - force the overlay on.
- `false` - force the overlay off.
- `undefined` - automatic, shown while `getData` is pending and hidden when it resolves.

## API Reference

| Property | Type | Default | Description |
| --- | --- | --- | --- |
| getData (required) | Function |  | Asynchronous callback to load data into the chart. |
