---
title: "Large Dataset Interactivity"
framework: react
version: "14.1.0"
---

# Large Dataset Interactivity

AG Charts is optimised to handle **large datasets with over 1 million points**, while maintaining full, smooth interactivity. No additional configuration or modules required - it just works out of the box.

#### Ordered Data

```tsx
import React, { useState, Fragment } from "react";
import { createRoot } from "react-dom/client";
import { AgCharts } from "ag-charts-react";
import {
  AgCartesianAxisOptions,
  AgCartesianChartOptions,
  AgCartesianSeriesOptions,
  AnimationModule,
  AreaSeriesModule,
  BarSeriesModule,
  BubbleSeriesModule,
  CandlestickSeriesModule,
  CategoryAxisModule,
  ContextMenuModule,
  CrosshairModule,
  HistogramSeriesModule,
  LegendModule,
  LineSeriesModule,
  ModuleRegistry,
  NavigatorModule,
  NumberAxisModule,
  OhlcSeriesModule,
  OrdinalTimeAxisModule,
  RangeAreaSeriesModule,
  RangeBarSeriesModule,
  ScatterSeriesModule,
  TimeAxisModule,
  ZoomModule,
} from "ag-charts-enterprise";
import { getData } from "./data";
import clone from "clone";

let dataLabel = "1K";
let seriesType = "Line";
let datapoints = 1e3;
const timeAxes: Record<string, AgCartesianAxisOptions> = {
  x: { type: "ordinal-time", parentLevel: { enabled: true } },
};
const numberAxes: Record<string, AgCartesianAxisOptions> = {
  x: { type: "number" },
};
const baseData = getData(1e6);
ModuleRegistry.registerModules([
  AnimationModule,
  AreaSeriesModule,
  BarSeriesModule,
  BubbleSeriesModule,
  CandlestickSeriesModule,
  CrosshairModule,
  HistogramSeriesModule,
  LegendModule,
  LineSeriesModule,
  NavigatorModule,
  NumberAxisModule,
  OhlcSeriesModule,
  OrdinalTimeAxisModule,
  RangeAreaSeriesModule,
  RangeBarSeriesModule,
  ScatterSeriesModule,
  TimeAxisModule,
  ZoomModule,
  CategoryAxisModule,
  ContextMenuModule,
]);

const ChartExample = () => {
  const [options, setOptions] = useState<AgCartesianChartOptions>({
    data: baseData.slice(-datapoints),
    title: { text: `${seriesType} with ${dataLabel} datapoints` },
    animation: { enabled: false },
    zoom: {
      enabled: true,
      axes: "x",
      anchorPointX: "pointer",
      anchorPointY: "pointer",
      autoScaling: {
        enabled: true,
      },
    },
    navigator: {
      enabled: true,
      miniChart: {
        enabled: true,
      },
    },
    series: [
      {
        type: "line",
        xKey: "timestamp",
        yKey: "close",
      },
    ],
    axes: timeAxes,
  });

  const setSeries = (type: string, label: string) => {
    const nextOptions = { ...options };

    seriesType = label;
    let series: AgCartesianSeriesOptions[] = [];
    switch (type) {
      case "bar":
      case "area":
      case "line":
        nextOptions.series = [
          {
            type,
            xKey: "timestamp",
            yKey: "high",
          },
        ];
        break;
      case "stacked-bar":
      case "stacked-area":
        const stackedType = type === "stacked-bar" ? "bar" : "area";
        nextOptions.series = [
          { type: stackedType, xKey: "timestamp", yKey: "open", stacked: true },
          {
            type: stackedType,
            xKey: "timestamp",
            yKey: "close",
            stacked: true,
          },
        ];
        break;
      case "range-area":
      case "range-bar":
        nextOptions.series = [
          {
            type,
            xKey: "timestamp",
            yLowKey: "low",
            yHighKey: "high",
          },
        ];
        break;
      case "candlestick":
      case "ohlc":
        nextOptions.series = [
          {
            type,
            xKey: "timestamp",
            lowKey: "low",
            highKey: "high",
            openKey: "open",
            closeKey: "close",
          },
        ];
        break;
      case "scatter":
        nextOptions.series = [
          {
            type,
            xKey: "x",
            yKey: "y",
            fillOpacity: 0.2,
            strokeOpacity: 0.2,
          },
        ];
        break;
      case "bubble":
        nextOptions.series = [
          {
            type,
            xKey: "x",
            yKey: "y",
            sizeKey: "size",
            fillOpacity: 0.2,
            strokeOpacity: 0.2,
          },
        ];
        break;
      case "histogram":
        nextOptions.series = [
          {
            type,
            xKey: "close",
          },
        ];
        break;
      default:
        return;
    }
    const newDatapoints = (nextOptions.series?.[0] as any)?.stacked
      ? datapoints / 2
      : datapoints;
    if (nextOptions.data?.length !== newDatapoints) {
      nextOptions.data = baseData.slice(-newDatapoints);
    }
    if (type == "bubble" || type == "scatter" || type == "histogram") {
      nextOptions.zoom!.axes = "xy";
      nextOptions.zoom!.autoScaling!.enabled = false;
      nextOptions.navigator!.enabled = false;
      nextOptions.axes = numberAxes;
    } else {
      nextOptions.zoom!.axes = "xy";
      nextOptions.zoom!.autoScaling!.enabled = true;
      nextOptions.navigator!.enabled = true;
      nextOptions.axes = timeAxes;
    }
    nextOptions.title!.text = `${seriesType} with ${dataLabel} datapoints`;

    setOptions(nextOptions);
  };

  const setData = (points: number, label: string) => {
    const nextOptions = { ...options };

    const newDatapoints = (nextOptions.series?.[0] as any)?.stacked
      ? points / 2
      : points;
    if (nextOptions.data?.length !== newDatapoints) {
      nextOptions.data = baseData.slice(-newDatapoints);
    }
    dataLabel = label;
    datapoints = points;
    nextOptions.title!.text = `${seriesType} with ${dataLabel} datapoints`;

    setOptions(nextOptions);
  };

  return (
    <Fragment>
      <div className="example-controls">
        <div className="controls-row">
          <span>Series Type:</span>
          <select
            onChange={(event) =>
              setSeries(
                event.target.value,
                event.target.selectedOptions[0].text,
              )
            }
          >
            <option value="line">Line</option>
            <option value="area">Area</option>
            <option value="bar">Bar</option>
            <hr />
            <option value="stacked-bar">Stacked Bar</option>
            <option value="stacked-area">Stacked Area</option>
            <hr />
            <option value="range-area">Range Area</option>
            <option value="range-bar">Range Bar</option>
            <hr />
            <option value="candlestick">Candlestick</option>
            <option value="ohlc">OHLC</option>
            <hr />
            <option value="scatter">Scatter</option>
            <option value="bubble">Bubble</option>
            <hr />
            <option value="histogram">Histogram</option>
          </select>
          <span className="gap-left">Data Size:</span>
          <button onClick={() => setData(1e3, "1K")}>1K</button>
          <button onClick={() => setData(1e4, "10K")}>10K</button>
          <button onClick={() => setData(1e5, "100K")}>100K</button>
          <button onClick={() => setData(5e5, "500K")}>500K</button>
          <button onClick={() => setData(1e6, "1M")}>1M</button>
        </div>
      </div>
      <AgCharts options={options} />
    </Fragment>
  );
};

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

[Live example: Ordered Data](https://www.ag-grid.com/charts/reactFunctionalTs/large-dataset-interactivity/examples/ordered-data)

In the above example:

- Use the controls to select different series types and data sizes.
- Use the mouse, [Navigator](https://www.ag-grid.com/charts/react/navigator/) or [zoom controls](https://www.ag-grid.com/charts/react/zoom/#axis-zoom-controls) to [zoom](https://www.ag-grid.com/charts/react/zoom/), [scroll](https://www.ag-grid.com/charts/react/zoom/#scrolling) and [pan](https://www.ag-grid.com/charts/react/zoom/#panning) the data.

> **Note**
>
> Performance may vary based on your specific use case, environment and hardware.

## How it works

Behind the scenes, AG Charts applies advanced data aggregation techniques, such as the [M4 algorithm](https://blog.ag-grid.com/optimizing-large-data-set-visualisations-with-the-m4-algorithm/), to ensure accurate representation across scales. As you zoom and pan, the chart dynamically adapts to the visible range, preserving both performance and clarity.
