Demonstrates handling realtime big data with different chart types using SciChart.js, High Performance JavaScript Charts
import "./styles.css";
import { ChangeEventHandler, useEffect, useRef, useState } from "react";
import { SettingsIcon, CloseIcon } from "./index";
import { BodyPortal } from "./Portal";
import { ChartModifierBase2D, ISciChartSubSurface } from "scichart";
import { GridLayoutModifier } from "./GridLayoutModifier";
import { ModifierGroup } from "./ModifierGroup";
import { createRegionStatisticsPieChart, getRegionStatisticsColumnChartConfig } from "./region-statistic-charts";
import { getMainChartConfig } from "./main-chart-config";
import { overviewOptions } from "./Overview";
import ThresholdSlider from "./ThresholdSlider";
import { SciChartReact as SciChart, SciChartNestedOverview, ChartGroupLoader } from "scichart-react";
import { appTheme } from "./appTheme";
import { getPageStatisticsChartConfig } from "./page-statistics-chart-config";
import { getServerLoadChartConfig } from "./server-load-chart-config";
import type {
TPageStatsConfigFuncResult,
TServerStatsChartConfigFuncResult,
TMainChartConfigFuncResult,
} from "./chart-types";
import { afterAllChartsInit } from "./after-all-charts-init";
import { VisibleRangeSynchronizationManager } from "./VisibleRangeSynchronizationManager";
import { useViewType } from "./containerSizeHooks";
function ServerTrafficDashboard() {
const ref = useRef<HTMLDivElement>(null);
const viewInfo = useViewType(ref);
const [isVisibleRangeSynced, setIsVisibleRangeSynced] = useState(true);
const [isHundredPercentCollection, setIsHundredPercentCollection] = useState(false);
const [isGridLayout, setIsGridLayout] = useState(false);
const pageStatisticChartRef = useRef<TPageStatsConfigFuncResult>(null);
const serverLoadChartRef = useRef<TServerStatsChartConfigFuncResult>(null);
const gridLayoutModifierRef = useRef<GridLayoutModifier>(null);
const [modifierGroup] = useState(new ModifierGroup());
const [axisSyncManager] = useState(new VisibleRangeSynchronizationManager());
useEffect(() => {
return () => {
pageStatisticChartRef.current = undefined;
serverLoadChartRef.current = undefined;
gridLayoutModifierRef.current = undefined;
};
}, []);
const onMainChartInit = (initResult: TMainChartConfigFuncResult) => {
const sciChartSurface = initResult.sciChartSurface;
const modifier = sciChartSurface.chartModifiers.getById("TotalRequestsCursorModifier");
const rollover = sciChartSurface.chartModifiers.getById("TotalRequestsRolloverModifier");
modifierGroup.add(modifier as ChartModifierBase2D, rollover as ChartModifierBase2D);
};
const onPageStatisticsChartInit = (initResult: TPageStatsConfigFuncResult) => {
pageStatisticChartRef.current = initResult;
const sciChartSurface = initResult.sciChartSurface;
const modifier = sciChartSurface.chartModifiers.getById("PageStatisticsRolloverModifier");
modifierGroup.add(modifier as ChartModifierBase2D);
};
const onServerLoadChartInit = (initResult: TServerStatsChartConfigFuncResult) => {
serverLoadChartRef.current = initResult;
const sciChartSurface = initResult.sciChartSurface;
gridLayoutModifierRef.current = sciChartSurface.chartModifiers.getById(
"GridLayoutModifier"
) as GridLayoutModifier;
const modifier = sciChartSurface.chartModifiers.getById("ServerLoadCursorModifier");
modifierGroup.add(modifier as ChartModifierBase2D);
};
const handleSyncVisibleRangeChange: ChangeEventHandler<HTMLInputElement> = (e) => {
axisSyncManager.enabled = !axisSyncManager.enabled;
setIsVisibleRangeSynced(!isVisibleRangeSynced);
};
const handleUsePercentage: ChangeEventHandler<HTMLInputElement> = (e) => {
pageStatisticChartRef.current.toggleIsHundredPercent();
setIsHundredPercentCollection(!isHundredPercentCollection);
};
const handleUseGridLayout: ChangeEventHandler<HTMLInputElement> = (e) => {
gridLayoutModifierRef.current.isGrid = !isGridLayout;
const subCharts = serverLoadChartRef.current.sciChartSurface.subCharts;
if (!isGridLayout) {
serverLoadChartRef.current.sciChartSurface.titleStyle.color = "transparent";
subCharts.forEach((subChart: ISciChartSubSurface) => {
const modifier = subChart.chartModifiers.getById("ServerLoadCursorModifier");
modifierGroup.add(modifier as ChartModifierBase2D);
});
} else {
serverLoadChartRef.current.sciChartSurface.titleStyle.color = appTheme.ForegroundColor;
subCharts.forEach((subChart: ISciChartSubSurface) => {
const modifier = subChart.chartModifiers.getById("ServerLoadCursorModifier");
modifierGroup.remove(modifier as ChartModifierBase2D);
});
}
setIsGridLayout(!isGridLayout);
};
const [isDialogOpen, setIsDialogOpen] = useState(false);
const handleClickOpen = () => {
setIsDialogOpen(true);
};
const handleClose = () => {
setIsDialogOpen(false);
};
const configurationDialog = isDialogOpen ? (
<BodyPortal>
<div
className="sc-modal-backdrop"
onClick={(event) => event.target === event.currentTarget && handleClose()}
onKeyDown={(event) => event.key === "Escape" && handleClose()}
>
<section className="sc-modal" role="dialog" aria-modal="true" aria-labelledby="server-config-title">
<header className="sc-modal-header">
<strong id="server-config-title">Chart Configurations</strong>
<button
className="sc-button sc-button-icon"
aria-label="Close chart configurations"
onClick={handleClose}
autoFocus
type="button"
>
<CloseIcon />
</button>
</header>
<div className="sc-modal-body">
<strong>Main Chart</strong>
<label className="sc-switch">
<input
type="checkbox"
checked={isVisibleRangeSynced}
onChange={handleSyncVisibleRangeChange}
/>
Sync X-Axis visible range
</label>
<strong>URL Statistics Chart</strong>
<label className="sc-switch">
<input
type="checkbox"
checked={isHundredPercentCollection}
onChange={handleUsePercentage}
/>
is 100% collection
</label>
<strong>Server Load Statistics Chart</strong>
<label className="sc-switch">
<input type="checkbox" checked={isGridLayout} onChange={handleUseGridLayout} />
is Grid Layout
</label>
</div>
</section>
</div>
</BodyPortal>
) : null;
return (
<div ref={ref} className="sc-chart-wrapper sc-server-traffic">
{viewInfo ? ( // checks if container was measured
<ChartGroupLoader
className="h-full sc-server-traffic-grid"
onInit={afterAllChartsInit(axisSyncManager)}
>
<div className="sc-server-traffic-settings m-1" title="Chart Configurations">
<button
className="sc-button sc-button-icon"
aria-label="Chart configurations"
onClick={handleClickOpen}
type="button"
>
<SettingsIcon fontSize="large" />
</button>
{configurationDialog}
</div>
<SciChart
initChart={getMainChartConfig(viewInfo)}
onInit={onMainChartInit}
className="relative sc-server-main-chart h-full"
>
<ThresholdSlider />
<SciChartNestedOverview style={{ height: "20%" }} options={overviewOptions} />
</SciChart>
<SciChart
initChart={getPageStatisticsChartConfig(viewInfo)}
onInit={onPageStatisticsChartInit}
className="sc-server-page-chart"
/>
<SciChart
initChart={getServerLoadChartConfig(viewInfo)}
onInit={onServerLoadChartInit}
className="sc-server-load-chart"
/>
<SciChart
initChart={getRegionStatisticsColumnChartConfig(viewInfo)}
className="sc-server-region-chart"
/>
<SciChart initChart={createRegionStatisticsPieChart} className="sc-server-region-pie" />
</ChartGroupLoader>
) : null}
</div>
);
}
export default ServerTrafficDashboard;
This React-based example, "Server Traffic Dashboard," demonstrates how to build a complex, interactive dashboard using SciChart.js within a React application. The dashboard brings together multiple charts—including a main time series chart, a page statistics chart, a server load chart, and region-based charts (both column and pie charts)—to provide a comprehensive view of server traffic and performance data.
The example is structured around React hooks and <SciChartReact/> components to manage lifecycle events and context. It uses a custom VisibleRangeSynchronizationManager to coordinate zooming and panning across different chart surfaces; see the Synchronizing Multiple Charts documentation for more details. Custom tooltip templates are implemented via option functions registered with the ChartBuilder API, as described in the Complex Options guide. Dynamic styling is achieved through a CustomPaletteProvider that adjusts point markers based on metadata, following the guidelines in the PaletteProvider API. Additionally, a specialized GridLayoutModifier enables the transformation of the server load chart into a grid of sub-charts with smooth animations, which is in line with techniques presented in the SubCharts Worked Example.
Key features include real-time data updates, interactive data filtering, and advanced tooltips that display aggregated statistics (such as average request duration). The dashboard also supports a 100% stacked column view for URL statistics, which aggregates data across different pages as detailed in our Stacked Column Chart resources. Interactive animations and hover effects are implemented using the GenericAnimation framework (Generic Animations), and mouse event synchronization across chart modifiers is managed by a custom ModifierGroup class.
The implementation demonstrates excellent integration with React by encapsulating individual charts into <SciChartReact/> components and coordinating them through a shared context and a chart group loader. Techniques for real-time updates are implemented to ensure efficient rendering and smooth performance, as recommended in Realtime Updates. Additionally, advanced synchronization of mouse events across multiple charts highlights best practices for interactive dashboards; more details can be found in the Synchronizing ChartModifier Mouse Events article. For further insights into integrating SciChart.js with React, developers are encouraged to review the React Charts with SciChart.js blog post.











