Syncfusion AI Assistant

How can I help you?

Dynamic data update in React Chart component

24 Feb 202624 minutes to read

The React Chart component provides methods to dynamically modify data without requiring a full chart refresh. This enables real-time data visualization, interactive features, and responsive user experiences. Common scenarios include adding sensor readings, removing outdated data points, replacing entire datasets, and enabling click-based data manipulation.

Adding a new data point

Use the addPoint method to dynamically append a new data point to a series. This is useful for real-time data streams, user interactions, or incremental data loading. The method accepts the following parameters:

  • Data point (required): The new data object to append to the series (must match the datasource structure)
  • Animation duration (optional): Duration in milliseconds for the entry animation
import * as React from "react";
import * as ReactDOM from "react-dom";
import {
  ChartComponent, SeriesCollectionDirective, SeriesDirective, Inject,
  Legend, Category, DataLabel, SplineSeries
} from '@syncfusion/ej2-react-charts';
import { data } from './datasource';

function App() {
  const primaryXAxis = { valueType: 'Category', enableTrim: false, majorTickLines: { width: 0 }, majorGridLines: { width: 0 } };
  const primaryYAxis = { minimum: 0, maximum: 800, labelFormat: '{value}M', edgeLabelPlacement: 'Shift' };
  const marker = {
    visible: true,
    dataLabel: {
      visible: true,
      position: 'Top',
      font: {
        fontWeight: '600'
      }
    }
  };
  const legendSettings = { visible: false };
  let chartInstance;
  function clickHandler() {
    chartInstance.series[0].addPoint({ x: 'Japan', y: 118.2 });
  }
  return (<div>
    <button value='add' onClick={clickHandler.bind(this)}>Add Point</button>
    <ChartComponent id='charts' ref={chart => chartInstance = chart} primaryXAxis={primaryXAxis} primaryYAxis={primaryYAxis} legendSettings={legendSettings} title='Internet Users - 2016' chartArea={{ border: { width: 1 } }}>
      <Inject services={[SplineSeries, Legend, DataLabel, Category]} />
      <SeriesCollectionDirective>
        <SeriesDirective dataSource={data} xName='x' yName='y' width={2} name='Users' type='Spline' marker={marker}>
        </SeriesDirective>
      </SeriesCollectionDirective>
    </ChartComponent></div>);
}
;
export default App;
ReactDOM.render(<App />, document.getElementById("charts"));
import * as React from "react";
import * as ReactDOM from "react-dom";
import {
  AxisModel, ChartComponent, SeriesCollectionDirective, SeriesDirective, Inject,
  Legend, Category, DataLabel, SplineSeries, MarkerSettingsModel, LegendSettingsModel
} from '@syncfusion/ej2-react-charts';
import { data } from './datasource';

function App() {
  const primaryXAxis: AxisModel = { valueType: 'Category', enableTrim: false, majorTickLines: { width: 0 }, majorGridLines: { width: 0 } };
  const primaryYAxis: AxisModel = { minimum: 0, maximum: 800, labelFormat: '{value}M', edgeLabelPlacement: 'Shift' };
  const marker: MarkerSettingsModel = {
    visible: true,
    dataLabel: {
      visible: true,
      position: 'Top',
      font: {
        fontWeight: '600'
      }
    }
  };
  const legendSettings: LegendSettingsModel = { visible: false };
  let chartInstance: ChartComponent;
  function clickHandler() {
    chartInstance.series[0].addPoint({ x: 'Japan', y: 118.2 });
  }

  return (<div>
    <button value='add' onClick={clickHandler.bind(this)}>Add Point</button>
    <ChartComponent id='charts' ref={chart => chartInstance = chart} primaryXAxis={primaryXAxis} primaryYAxis={primaryYAxis} legendSettings={legendSettings} title='Internet Users - 2016' chartArea={{ border: { width: 1 } }}>
      <Inject services={[SplineSeries, Legend, DataLabel, Category]} />
      <SeriesCollectionDirective>
        <SeriesDirective dataSource={data} xName='x' yName='y' width={2} name='Users' type='Spline' marker={marker}>
        </SeriesDirective>
      </SeriesCollectionDirective>
    </ChartComponent></div>)
};
export default App;
ReactDOM.render(<App />, document.getElementById("charts"));
export let data = [
    { x: "Germany",       y: 72 },
    { x: "Russia",        y: 103.1 },
    { x: "Brazil",        y: 139.1 },
    { x: "India",         y: 462.1 },
    { x: "China",         y: 721.4 },
    { x: "USA",           y: 286.9 },
    { x: "Great Britain", y: 115.1 },
    { x: "Nigeria",       y: 97.2 }
];
export let data: Object[] = [
    { x: "Germany",       y: 72 },
    { x: "Russia",        y: 103.1 },
    { x: "Brazil",        y: 139.1 },
    { x: "India",         y: 462.1 },
    { x: "China",         y: 721.4 },
    { x: "USA",           y: 286.9 },
    { x: "Great Britain", y: 115.1 },
    { x: "Nigeria",       y: 97.2 }
];

Removing an existing data point

Use the removePoint method to dynamically delete a data point from a series by its index. This is useful for filtering data, removing outliers, or responding to user actions. The method accepts the following parameters:

  • Point index (required): The zero-based index of the data point to remove
  • Animation duration (optional): Duration in milliseconds for the exit animation
import * as React from "react";
import * as ReactDOM from "react-dom";
import {
  ChartComponent, SeriesCollectionDirective, SeriesDirective, Inject,
  Legend, Category, DataLabel, SplineSeries
} from '@syncfusion/ej2-react-charts';
import { data } from './datasource';

function App() {
  const primaryXAxis = { valueType: 'Category', enableTrim: false, majorTickLines: { width: 0 }, majorGridLines: { width: 0 } };
  const primaryYAxis = { minimum: 0, maximum: 800, labelFormat: '{value}M', edgeLabelPlacement: 'Shift' };
  const marker = {
    visible: true,
    dataLabel: {
      visible: true,
      position: 'Top',
      font: {
        fontWeight: '600'
      }
    }
  };
  const legendSettings = { visible: false };
  let chartInstance;
  function clickHandler() {
    chartInstance.series[0].removePoint(0);
  }
  return (<div>
    <button value='remove' onClick={clickHandler.bind(this)}>Remove Point</button>
    <ChartComponent id='charts' ref={chart => chartInstance = chart} primaryXAxis={primaryXAxis} primaryYAxis={primaryYAxis} legendSettings={legendSettings} title='Internet Users - 2016' chartArea={{ border: { width: 1 } }}>
      <Inject services={[SplineSeries, Legend, DataLabel, Category]} />
      <SeriesCollectionDirective>
        <SeriesDirective dataSource={data} xName='x' yName='y' width={2} name='Users' type='Spline' marker={marker}>
        </SeriesDirective>
      </SeriesCollectionDirective>
    </ChartComponent></div>);
}
;
export default App;
ReactDOM.render(<App />, document.getElementById("charts"));
import * as React from "react";
import * as ReactDOM from "react-dom";
import {
  AxisModel, ChartComponent, SeriesCollectionDirective, SeriesDirective, Inject,
  Legend, Category, DataLabel, SplineSeries, MarkerSettingsModel, LegendSettingsModel
} from '@syncfusion/ej2-react-charts';
import { data } from './datasource';

function App() {
  const primaryXAxis: AxisModel = { valueType: 'Category', enableTrim: false, majorTickLines: { width: 0 }, majorGridLines: { width: 0 } };
  const primaryYAxis: AxisModel = { minimum: 0, maximum: 800, labelFormat: '{value}M', edgeLabelPlacement: 'Shift' };
  const marker: MarkerSettingsModel = {
    visible: true,
    dataLabel: {
      visible: true,
      position: 'Top',
      font: {
        fontWeight: '600'
      }
    }
  };
  const legendSettings: LegendSettingsModel = { visible: false };
  let chartInstance: ChartComponent;
  function clickHandler() {
    chartInstance.series[0].removePoint(0);
  }

  return (<div>
    <button value='remove' onClick={clickHandler.bind(this)}>Remove Point</button>
    <ChartComponent id='charts' ref={chart => chartInstance = chart} primaryXAxis={primaryXAxis} primaryYAxis={primaryYAxis} legendSettings={legendSettings} title='Internet Users - 2016' chartArea={{ border: { width: 1 } }}>
      <Inject services={[SplineSeries, Legend, DataLabel, Category]} />
      <SeriesCollectionDirective>
        <SeriesDirective dataSource={data} xName='x' yName='y' width={2} name='Users' type='Spline' marker={marker}>
        </SeriesDirective>
      </SeriesCollectionDirective>
    </ChartComponent></div>)
};
export default App;
ReactDOM.render(<App />, document.getElementById("charts"));
export let data = [
    { x: "Germany",       y: 72 },
    { x: "Russia",        y: 103.1 },
    { x: "Brazil",        y: 139.1 },
    { x: "India",         y: 462.1 },
    { x: "China",         y: 721.4 },
    { x: "USA",           y: 286.9 },
    { x: "Great Britain", y: 115.1 },
    { x: "Nigeria",       y: 97.2 }
];
export let data: Object[] = [
    { x: "Germany",       y: 72 },
    { x: "Russia",        y: 103.1 },
    { x: "Brazil",        y: 139.1 },
    { x: "India",         y: 462.1 },
    { x: "China",         y: 721.4 },
    { x: "USA",           y: 286.9 },
    { x: "Great Britain", y: 115.1 },
    { x: "Nigeria",       y: 97.2 }
];

Replacing entire data points

Use the setData method to replace all data points in a series with a new dataset. This is useful for category switching, time range changes, or complete data refreshes. The method accepts the following parameters:

  • New data source (required): The complete new dataset array to display
  • Animation duration (optional): Duration in milliseconds for the transition animation
import * as React from "react";
import * as ReactDOM from "react-dom";
import { ChartComponent, SeriesCollectionDirective, SeriesDirective, Inject, ColumnSeries, Category } from '@syncfusion/ej2-react-charts';
import { data } from './datasource';

function App() {
  const primaryXAxis = { valueType: 'Category', majorGridLines: { width: 0 }, labelStyle: { size: '12px' }, labelIntersectAction: 'Rotate90' };
  const primaryYAxis = { title: 'Sales (in percentage)', labelFormat: '{value}%', lineStyle: { width: 0 }, majorTickLines: { width: 0 }, interval: 5, minimum: 0, maximum: 100 };
  let chartInstance;
  function clickHandler() {
    const newData = data.map((item) => {
      const value = getRandomInt(10, 90);
      return { x: item.x, y: value };
    });
    if (chartInstance.series.length > 0) {
      chartInstance.series[0].setData(newData, 500);
    }
  }

  function getRandomInt(min, max) {
    return Math.floor(Math.random() * (max - min + 1)) + min;
  }

  let axisRangeCalculated = (args) => {
    if (args.axis.name === 'primaryYAxis') {
      args.maximum = args.maximum > 100 ? 100 : args.maximum;
      if (args.maximum > 80) {
        args.interval = 20;
      }
      else if (args.maximum > 40) {
        args.interval = 10;
      }
    }
  }
  return (<div>
    <button value='update' onClick={clickHandler.bind(this)}>Update Data</button>
    <ChartComponent id='charts' ref={chart => chartInstance = chart} primaryXAxis={primaryXAxis} primaryYAxis={primaryYAxis} title='Sales by product' chartArea={{ border: { width: 0 } }} axisRangeCalculated={axisRangeCalculated.bind(this)}>
      <Inject services={[ColumnSeries, Category]} />
      <SeriesCollectionDirective>
        <SeriesDirective dataSource={data} xName='x' yName='y' cornerRadius={{ topLeft: 15, topRight: 15 }} columnWidth={0.5} type='Column'>
        </SeriesDirective>
      </SeriesCollectionDirective>
    </ChartComponent></div>);
}
;
export default App;
ReactDOM.render(<App />, document.getElementById("charts"));
import * as React from "react";
import * as ReactDOM from "react-dom";
import {
  AxisModel, ChartComponent, SeriesCollectionDirective, SeriesDirective, Inject,
  ColumnSeries, Category, IAxisRangeCalculatedEventArgs
} from '@syncfusion/ej2-react-charts';
import { data } from './datasource';

function App() {
  const primaryXAxis: AxisModel = { valueType: 'Category', majorGridLines: { width: 0 }, labelStyle: { size: '12px' }, labelIntersectAction: 'Rotate90' };
  const primaryYAxis: AxisModel = { title: 'Sales (in percentage)', labelFormat: '{value}%', lineStyle: { width: 0 }, majorTickLines: { width: 0 }, interval: 5, minimum: 0, maximum: 100 };
  let chartInstance: ChartComponent;
  function clickHandler() {
    const newData = data.map((item: { x: string, y: number }) => {
      const value: number = getRandomInt(10, 90);
      return { x: item.x, y: value };
    });
    if (chartInstance.series.length > 0) {
      chartInstance.series[0].setData(newData, 500);
    }
  }

  function getRandomInt(min: number, max: number) {
    return Math.floor(Math.random() * (max - min + 1)) + min;
  }

  let axisRangeCalculated = (args: IAxisRangeCalculatedEventArgs): void => {
    if (args.axis.name === 'primaryYAxis') {
      args.maximum = args.maximum as number > 100 ? 100 : args.maximum;
      if (args.maximum > 80) {
        args.interval = 20;
      }
      else if (args.maximum > 40) {
        args.interval = 10;
      }
    }
  }

  return (<div>
    <button value='update' onClick={clickHandler.bind(this)}>Update Data</button>
    <ChartComponent id='charts' ref={chart => chartInstance = chart} primaryXAxis={primaryXAxis} primaryYAxis={primaryYAxis} title='Sales by product' chartArea={{ border: { width: 0 } }} axisRangeCalculated={axisRangeCalculated.bind(this)}>
      <Inject services={[ColumnSeries, Category]} />
      <SeriesCollectionDirective>
        <SeriesDirective dataSource={data} xName='x' yName='y' cornerRadius={{ topLeft: 15, topRight: 15 }} columnWidth={0.5} type='Column'>
        </SeriesDirective>
      </SeriesCollectionDirective>
    </ChartComponent></div>)
};
export default App;
ReactDOM.render(<App />, document.getElementById("charts"));
export let data = [
    { x: 'Jewellery', y: 75 },
    { x: 'Shoes', y: 45 },
    { x: 'Footwear', y: 73 },
    { x: 'Pet Services', y: 53 },
    { x: 'Business Clothing', y: 85 },
    { x: 'Office Supplies', y: 68 },
    { x: 'Food', y: 45 }
];
export let data: any[] = [
    { x: 'Jewellery', y: 75 },
    { x: 'Shoes', y: 45 },
    { x: 'Footwear', y: 73 },
    { x: 'Pet Services', y: 53 },
    { x: 'Business Clothing', y: 85 },
    { x: 'Office Supplies', y: 68 },
    { x: 'Food', y: 45 }
];

Click to add or remove a data point

Enable users to add or remove data points by clicking on the chart. Listen to the chartMouseClick event to capture click coordinates and point information. When a user clicks within the chart area, extract the x and y axis values from the event arguments. If the location is empty, use addPoint to add a new data point at those coordinates. If a user clicks on an existing data point, identify its index and use removePoint to delete it. This creates an intuitive interface for data exploration and editing.

import * as React from "react";
import * as ReactDOM from "react-dom";
import { ChartComponent, SeriesCollectionDirective, SeriesDirective, Inject, LineSeries, DataLabel, Tooltip } from '@syncfusion/ej2-react-charts';
import { data } from './datasource';

function App() {
  const primaryXAxis = { edgeLabelPlacement: 'Shift', rangePadding: 'Additional', majorGridLines: { width: 0 } };
  const primaryYAxis = { title: 'Value', interval: 20, lineStyle: { width: 0 }, majorTickLines: { width: 0 } };
  const marker = {
    visible: true,
    isFilled: true,
    border: {
      width: 2,
      color: 'White'
    },
    width: 13,
    height: 13
  };
  const tooltip = { enable: true };
  let chartInstance;
  const axisRangeCalculated = (args) => {
    if (args.axis.name === 'primaryXAxis') {
      if (args.interval < 10) {
        args.maximum = args.maximum + 10;
        args.minimum = args.minimum - 10;
        args.interval = 10;
      }
    }
    if (args.axis.name === 'primaryYAxis') {
      if (args.maximum <= 60) {
        args.interval = 10;
      }
    }
  }

  const chartMouseClick = (args) => {
    let isRemoved = false;
    if (args.axisData) {
      for (let i = 0; i < (chartInstance.series[0]).points.length; i++) {
        const markerWidth = (chartInstance.series[0]).marker.width / 2;
        let roundedX = Math.round(args.axisData['primaryXAxis']) + markerWidth;
        let roundedY = Math.round(args.axisData['primaryYAxis']) + markerWidth;
        let pointX = Math.round((chartInstance.series[0]).points[i].x) + markerWidth;
        let pointY = Math.round((chartInstance.series[0]).points[i].y) + markerWidth;
        if ((roundedX === pointX || roundedX + 1 === pointX || roundedX - 1 === pointX) &&
          (roundedY === pointY || roundedY + 1 === pointY || roundedY - 1 === pointY)) {
          if ((chartInstance.series[0]).points.length > 1) {
            const points = (chartInstance.series[0]).points;
            const duration = i === 0 || i === points[points.length - 1].index ? 500 : 0;
            chartInstance.series[0].removePoint(i, duration);
          }
          isRemoved = true;
        }
      }
      if (!isRemoved) {
        chartInstance.series[0].addPoint({ x: Math.round(args.axisData['primaryXAxis']), y: Math.round(args.axisData['primaryYAxis']) });
      }
    }
  };
  return (<div>
    <ChartComponent id='charts' ref={chart => chartInstance = chart} primaryXAxis={primaryXAxis} primaryYAxis={primaryYAxis} tooltip={tooltip} title='User supplied data' chartArea={{ border: { width: 0 } }} axisRangeCalculated={axisRangeCalculated.bind(this)} chartMouseClick={chartMouseClick.bind(this)}>
      <Inject services={[LineSeries, DataLabel, Tooltip]} />
      <SeriesCollectionDirective>
        <SeriesDirective dataSource={data} xName='x' yName='y' marker={marker} width={3} type='Line'>
        </SeriesDirective>
      </SeriesCollectionDirective>
    </ChartComponent></div>);
}
;
export default App;
ReactDOM.render(<App />, document.getElementById("charts"));
import * as React from "react";
import * as ReactDOM from "react-dom";
import {
  AxisModel, ChartComponent, SeriesCollectionDirective, SeriesDirective, Inject,
  LineSeries, DataLabel, Tooltip, MarkerSettingsModel, IAxisRangeCalculatedEventArgs, Series, TooltipSettingsModel, IMouseEventArgs
} from '@syncfusion/ej2-react-charts';
import { data } from './datasource';

function App() {
  const primaryXAxis: AxisModel = { edgeLabelPlacement: 'Shift', rangePadding: 'Additional', majorGridLines: { width: 0 } };
  const primaryYAxis: AxisModel = { title: 'Value', interval: 20, lineStyle: { width: 0 }, majorTickLines: { width: 0 } };
  const marker: MarkerSettingsModel = {
    visible: true,
    isFilled: true,
    border: {
      width: 2,
      color: 'White'
    },
    width: 13,
    height: 13
  };
  const tooltip: TooltipSettingsModel = { enable: true };
  let chartInstance: ChartComponent;
  const axisRangeCalculated = (args: IAxisRangeCalculatedEventArgs): void => {
    if (args.axis.name === 'primaryXAxis') {
      if (args.interval < 10) {
        args.maximum = args.maximum + 10;
        args.minimum = args.minimum - 10;
        args.interval = 10;
      }
    }
    if (args.axis.name === 'primaryYAxis') {
      if (args.maximum <= 60) {
        args.interval = 10;
      }
    }
  }

  const chartMouseClick = (args: IMouseEventArgs): void => {
    let isRemoved: boolean = false;
    if (args.axisData) {
      for (let i: number = 0; i < (chartInstance.series[0] as Series).points.length; i++) {
        const markerWidth: number = (chartInstance.series[0] as Series).marker.width / 2;
        let roundedX: number = Math.round(args.axisData['primaryXAxis']) + markerWidth;
        let roundedY: number = Math.round(args.axisData['primaryYAxis']) + markerWidth;
        let pointX: number = Math.round((chartInstance.series[0] as Series).points[i].x as number) + markerWidth;
        let pointY: number = Math.round((chartInstance.series[0] as Series).points[i].y as number) + markerWidth;
        if ((roundedX === pointX || roundedX + 1 === pointX || roundedX - 1 === pointX) &&
          (roundedY === pointY || roundedY + 1 === pointY || roundedY - 1 === pointY)) {
          if ((chartInstance.series[0] as Series).points.length > 1) {
            const points = (chartInstance.series[0] as Series).points;
            const duration: number = i === 0 || i === points[points.length - 1].index ? 500 : 0;
            chartInstance.series[0].removePoint(i, duration);
          }
          isRemoved = true;
        }
      }
      if (!isRemoved) {
        chartInstance.series[0].addPoint({ x: Math.round(args.axisData['primaryXAxis']), y: Math.round(args.axisData['primaryYAxis']) });
      }
    }
  };

  return (<div>
    <ChartComponent id='charts' ref={chart => chartInstance = chart} primaryXAxis={primaryXAxis} primaryYAxis={primaryYAxis} tooltip={tooltip} title='User supplied data' chartArea={{ border: { width: 0 } }} axisRangeCalculated={axisRangeCalculated.bind(this)} chartMouseClick={chartMouseClick.bind(this)}>
      <Inject services={[LineSeries, DataLabel, Tooltip]} />
      <SeriesCollectionDirective>
        <SeriesDirective dataSource={data} xName='x' yName='y' marker={marker} width={3} type='Line'>
        </SeriesDirective>
      </SeriesCollectionDirective>
    </ChartComponent></div>)
};
export default App;
ReactDOM.render(<App />, document.getElementById("charts"));
export let data = [
    { x: 20, y: 20 },
    { x: 80, y: 80 }
];
export let data: Object[] = [
    { x: 20, y: 20 },
    { x: 80, y: 80 }
];