React bindings for ChartGPU: MIT-licensed WebGPU charts for dense real-time, multi-series and multi-panel dashboards.
chartgpu-react is a thin React + TypeScript wrapper around @chartgpu/chartgpu: lifecycle, resize, events, refs, and multi-chart GPU sharing in React. Core charting stays in ChartGPU (MIT commercial embed, zero npm runtime dependencies in core, WebGPU required, no WebGL fallback).
Use it when Chart.js, ECharts, or uPlot hit streaming or multi-panel walls. Commercial GPU seats often ship WebGL fallback and broader catalog; ChartGPU is the open WebGPU-only embed.
Demo and docs: chartgpu.io · docs · streaming dashboards · core repo
npm install chartgpu-react @chartgpu/chartgpu react react-domPeer dependency: @chartgpu/chartgpu ^0.3.6 (aligned with this package’s 0.3.x line). React 18 or 19.
import { ChartGPU } from 'chartgpu-react';
import type { ChartGPUOptions } from 'chartgpu-react';
function MyChart() {
const options: ChartGPUOptions = {
series: [
{
type: 'line',
data: {
x: new Float64Array([0, 1, 2, 3]),
y: new Float64Array([0, 1, 4, 9]),
},
lineStyle: { width: 2, color: '#667eea' },
},
],
xAxis: { type: 'value' },
yAxis: { type: 'value' },
};
return <ChartGPU options={options} style={{ width: '100%', height: '400px' }} />;
}Object / [x,y] tuples are fine for tiny demos; prefer typed-array columns at scale.
| React lifecycle | Async create/dispose, debounced ResizeObserver sizing |
| Dense real-time jobs | Multi-series streaming, multi-panel dashboards, finance, heatmaps (via core) |
| Shared-device multi-panel | useGPUContext / gpuContext prop (recommended for ≥3 charts); useConnectCharts / connectCharts |
| Ring FIFO streaming | ref.appendData(..., { maxPoints }); heatmap/surface stream APIs on core |
| Events and refs | onClick, onCrosshairMove, onZoomChange, onDataAppend, onDeviceLost, …; ChartGPUHandle imperative API |
| MIT commercial embed | MIT wrapper; core density stays free under MIT with no feature gates on FIFO, zoom, multi-chart, or finance series |
| WebGPU-only | Same browser gate as core; no WebGL fallback |
ChartGPUcomponent (recommended): create/dispose, resize, event props,gpuContext,ref/ChartGPUHandle- Hooks:
useChartGPU,useGPUContext,useConnectCharts - Deprecated:
ChartGPUChart(useChartGPU) - Re-exports from core:
createChart,connectCharts,createAnnotationAuthoring,createPipelineCache,getPipelineCacheStats,destroyPipelineCache
Details: API reference · Getting started
import { useEffect, useRef } from 'react';
import { ChartGPU } from 'chartgpu-react';
import type { ChartGPUHandle } from 'chartgpu-react';
function StreamingChart() {
const ref = useRef<ChartGPUHandle>(null);
const t = useRef(0);
useEffect(() => {
const id = window.setInterval(() => {
const x0 = t.current;
const x = new Float64Array([x0, x0 + 1, x0 + 2]);
const y = new Float64Array([Math.sin(x0 * 0.05), Math.sin((x0 + 1) * 0.05), Math.sin((x0 + 2) * 0.05)]);
t.current += 3;
// Density path: column payload + fixed-capacity ring
ref.current?.appendData(0, { x, y }, { maxPoints: 50_000 });
}, 16);
return () => window.clearInterval(id);
}, []);
return (
<ChartGPU
ref={ref}
options={{
autoScroll: true,
series: [
{
type: 'line',
data: { x: new Float64Array(0), y: new Float64Array(0) },
lineStyle: { width: 2, color: '#4facfe' },
},
],
xAxis: { type: 'value' },
yAxis: { type: 'value' },
}}
style={{ width: '100%', height: 320 }}
/>
);
}import { ChartGPU, useGPUContext } from 'chartgpu-react';
function Dashboard() {
const { adapter, device, pipelineCache, isReady, error } = useGPUContext();
if (error) return <div>{error.message}</div>;
if (!isReady || !adapter || !device) return <div>Loading…</div>;
const gpuContext = pipelineCache
? { adapter, device, pipelineCache }
: { adapter, device };
return (
<>
<ChartGPU options={optionsA} gpuContext={gpuContext} style={{ height: 240 }} />
<ChartGPU options={optionsB} gpuContext={gpuContext} style={{ height: 240 }} />
<ChartGPU options={optionsC} gpuContext={gpuContext} style={{ height: 240 }} />
</>
);
}Recommended for ≥3 charts. Full recipes: streaming dashboards · chart-sync recipe · core multi-chart cookbook
import { ChartGPU } from 'chartgpu-react';
import type { ChartGPUCrosshairMovePayload } from 'chartgpu-react';
<ChartGPU
options={options}
onCrosshairMove={(p: ChartGPUCrosshairMovePayload) => {
console.log('crosshair x:', p.x, 'source:', p.source);
}}
/>;import { connectCharts } from 'chartgpu-react';
const disconnect = connectCharts([chartA, chartB], { syncZoom: true });
// later: disconnect();Prefer useConnectCharts(...) when instances come from onReady / useChartGPU.
import { useEffect, useRef } from 'react';
import { ChartGPU } from 'chartgpu-react';
import type { ChartGPUHandle } from 'chartgpu-react';
function ExternalLoop({ options }) {
const ref = useRef<ChartGPUHandle>(null);
useEffect(() => {
let raf = 0;
const loop = () => {
if (ref.current?.needsRender()) ref.current.renderFrame();
raf = requestAnimationFrame(loop);
};
raf = requestAnimationFrame(loop);
return () => cancelAnimationFrame(raf);
}, []);
return <ChartGPU ref={ref} options={{ ...options, renderMode: 'external' }} />;
}import { useEffect, useRef, useState } from 'react';
import { ChartGPU, createAnnotationAuthoring } from 'chartgpu-react';
import type { ChartGPUHandle, ChartGPUInstance } from 'chartgpu-react';
function AnnotationAuthoringExample({ options }) {
const chartRef = useRef<ChartGPUHandle>(null);
const [chart, setChart] = useState<ChartGPUInstance | null>(null);
useEffect(() => {
const container = chartRef.current?.getContainer();
const instance = chartRef.current?.getChart();
if (!container || !instance) return;
const authoring = createAnnotationAuthoring(container, instance, {
enableContextMenu: true,
});
return () => authoring.dispose();
}, [chart]);
return <ChartGPU ref={chartRef} options={options} onReady={setChart} />;
}import { useEffect, useRef } from 'react';
import { ChartGPU } from 'chartgpu-react';
import type { ChartGPUHandle, ChartGPUOptions, OHLCDataPoint } from 'chartgpu-react';
function CandlestickStreaming() {
const ref = useRef<ChartGPUHandle>(null);
const options: ChartGPUOptions = {
xAxis: { type: 'time' },
dataZoom: [{ type: 'inside' }, { type: 'slider' }],
autoScroll: true,
series: [{ type: 'candlestick', sampling: 'ohlc', data: [] }],
};
useEffect(() => {
const timer = window.setInterval(() => {
const next: OHLCDataPoint = {
timestamp: Date.now(),
open: 100,
close: 102,
low: 99,
high: 103,
};
ref.current?.appendData(0, [next]);
}, 500);
return () => window.clearInterval(timer);
}, []);
return <ChartGPU ref={ref} options={options} style={{ height: 360 }} />;
}| Docs hub | Guides and series docs |
| Getting started | Install and first chart |
| Streaming dashboards | Shared device, multi-chart |
| Performance | Density, sampling, GPU sharing |
| Getting started | React install and first component |
| API | Component, hooks, handle |
| Recipes | Crosshair, sync, streaming, annotations, dataZoom |
npm install
npm run dev
# http://localhost:3000/examples/index.htmlSee examples/main.tsx.
No WebGL fallback. Gate unsupported browsers in your app (capability detect; never a blank canvas).
| Browser | Notes |
|---|---|
| Chrome / Edge | 113+ |
| Safari | 18+ |
| Firefox | Windows 114+, macOS 145+, Linux still incomplete on gpuweb status |
if (!navigator.gpu) {
// fail closed: show UI, do not leave an empty chart
}WebGPU-only is intentional. Need Canvas/SVG or dual WebGL+WebGPU? Use a stack that ships a fallback.
npm install
npm run typecheck
npm run build
npm run dev# From sibling ChartGPU clone (directory name may vary)
cd ../ChartGPU
npm link
cd ../chartgpu-react
npm link @chartgpu/chartgpu
npm run build
npm run devUnlink:
npm unlink @chartgpu/chartgpu
npm installimport type {
ChartGPUInstance,
ChartGPUOptions,
ChartGPUEventPayload,
ChartGPUCrosshairMovePayload,
ChartGPUZoomRangeChangePayload,
ChartGPUHitTestResult,
ChartGPUHitTestMatch,
ChartSyncOptions,
LineSeriesConfig,
AreaSeriesConfig,
BarSeriesConfig,
ScatterSeriesConfig,
PieSeriesConfig,
SeriesConfig,
DataPoint,
OHLCDataPoint,
TooltipConfig,
PerformanceMetrics,
} from 'chartgpu-react';Issues and pull requests welcome. For larger changes, open an issue first.
MIT. Free for commercial embedding. ChartGPU core keeps density, FIFO, multi-chart, and finance series in the open core.
- ChartGPU — core WebGPU charting library
- chartgpu.io — demos and docs
