echarts-for-react is a React wrapper library for Apache ECharts that provides comprehensive charting capabilities through a simple React component interface. It offers both a full-featured component with the entire ECharts library and a lightweight core component for tree-shaking and bundle optimization.
npm install echarts-for-react echartsimport ReactECharts from "echarts-for-react";
import type { EChartsReactProps, EChartsOption, EChartsInstance } from "echarts-for-react";For tree-shaking (core component):
import ReactEChartsCore from "echarts-for-react/lib/core";
import * as echarts from "echarts/core";
import type { EChartsReactProps } from "echarts-for-react";CommonJS:
const ReactECharts = require("echarts-for-react");
const { EChartsReactProps, EChartsOption, EChartsInstance } = require("echarts-for-react");import React from "react";
import ReactECharts from "echarts-for-react";
// Basic chart component
function MyChart() {
const option = {
xAxis: {
type: 'category',
data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
},
yAxis: {
type: 'value'
},
series: [{
data: [820, 932, 901, 934, 1290, 1330, 1320],
type: 'line',
smooth: true
}]
};
return (
<ReactECharts
option={option}
style={{ height: '400px', width: '100%' }}
className="my-chart"
/>
);
}echarts-for-react is built around a hierarchical component structure:
The main ReactECharts component with complete ECharts functionality, extends EChartsReactCore.
/**
* Main React component for ECharts with full library included
* Extends EChartsReactCore with pre-loaded echarts library
*/
export default class ReactECharts extends EChartsReactCore {
constructor(props: EChartsReactProps);
/**
* Get the ECharts instance for direct API access
* @returns ECharts instance object
*/
getEchartsInstance(): EChartsInstance;
}Tree-shakeable base component for custom ECharts builds.
/**
* Core React component for ECharts with manual module imports
* Base class that ReactECharts extends
*/
export default class EChartsReactCore extends React.PureComponent<EChartsReactProps> {
/** ECharts render container element */
public ele: HTMLElement;
/** ECharts library entry (protected) */
protected echarts: any;
constructor(props: EChartsReactProps);
/**
* Initialize ECharts instance asynchronously with proper sizing
* @returns Promise resolving to ECharts instance
*/
initEchartsInstance(): Promise<ECharts>;
/**
* Get the existing ECharts instance
* @returns ECharts instance object
*/
getEchartsInstance(): EChartsInstance;
/** Update ECharts options and return instance */
private updateEChartsOption(): EChartsInstance;
/** Resize chart wrapper with initial resize check */
private resize(): void;
/** Dispose echarts instance and clear size-sensor */
private dispose(): void;
}Complete props interface for both components.
interface EChartsReactProps {
/** ECharts library entry for custom imports (required for ReactEChartsCore) */
readonly echarts?: any;
/** CSS class name for the chart container */
readonly className?: string;
/** CSS styles for the chart container */
readonly style?: React.CSSProperties;
/** ECharts configuration option (required) */
readonly option: EChartsOption;
/** ECharts theme config - theme name string or theme object */
readonly theme?: string | Record<string, any>;
/** Don't merge with existing data when updating, default false */
readonly notMerge?: boolean;
/** Replace merge config for chart updates, default null */
readonly replaceMerge?: string | string[];
/** Lazy update config for chart updates, default false */
readonly lazyUpdate?: boolean;
/** Show loading mask, default false */
readonly showLoading?: boolean;
/** Loading option configuration, default null */
readonly loadingOption?: any;
/** ECharts initialization options, default {} */
readonly opts?: Opts;
/** Callback when chart is ready with ECharts instance */
readonly onChartReady?: (instance: EChartsInstance) => void;
/** Event bindings object with event names as keys, default {} */
readonly onEvents?: Record<string, Function>;
/** Function to determine if chart options should update */
readonly shouldSetOption?: (prevProps: EChartsReactProps, props: EChartsReactProps) => boolean;
/** Enable automatic resize on window resize, default true */
readonly autoResize?: boolean;
}Configuration options for ECharts instance initialization.
interface Opts {
/** Device pixel ratio */
readonly devicePixelRatio?: number;
/** Renderer type - 'canvas' or 'svg' */
readonly renderer?: 'canvas' | 'svg';
/** Chart width - number, null, undefined, or 'auto' */
readonly width?: number | null | undefined | 'auto';
/** Chart height - number, null, undefined, or 'auto' */
readonly height?: number | null | undefined | 'auto';
/** Locale setting for internationalization */
readonly locale?: string;
}Core types for ECharts integration.
import type { EChartsType } from 'echarts';
import type { CSSProperties } from 'react';
/** ECharts option configuration type - resolved to any to avoid type conflicts */
type EChartsOption = any;
/** ECharts instance type from echarts library */
type EChartsInstance = EChartsType;Internal helper functions used by the library.
import { bind, clear } from 'size-sensor';
import isEqual from 'fast-deep-equal';
/**
* Select specific properties from an object
* @param obj - Source object
* @param keys - Array of property keys to pick
* @returns New object with only selected properties
*/
function pick(obj: Record<string, unknown>, keys: string[]): Record<string, unknown>;
/**
* Deep equality comparison using fast-deep-equal
* @param a - First value to compare
* @param b - Second value to compare
* @returns True if values are deeply equal
*/
function isEqual<T>(a: T, b: T): boolean;
/**
* Check if value is a function
* @param v - Value to check
* @returns True if value is a function
*/
function isFunction(v: any): boolean;
/**
* Check if value is a string
* @param v - Value to check
* @returns True if value is a string
*/
function isString(v: any): boolean;The library relies on these external dependencies:
/** Size sensor for responsive chart resizing */
import { bind, clear } from 'size-sensor';
/** Fast deep equality comparison */
import isEqual from 'fast-deep-equal';import React from "react";
import ReactEChartsCore from "echarts-for-react/lib/core";
import * as echarts from "echarts/core";
import { BarChart } from "echarts/charts";
import { GridComponent, TooltipComponent, TitleComponent } from "echarts/components";
import { CanvasRenderer } from "echarts/renderers";
// Register required components
echarts.use([TitleComponent, TooltipComponent, GridComponent, BarChart, CanvasRenderer]);
function OptimizedChart() {
const option = {
title: { text: 'Sample Bar Chart' },
tooltip: {},
xAxis: { data: ['A', 'B', 'C', 'D', 'E'] },
yAxis: {},
series: [{ type: 'bar', data: [10, 22, 28, 15, 35] }]
};
return (
<ReactEChartsCore
echarts={echarts}
option={option}
style={{ height: '400px' }}
/>
);
}import React from "react";
import ReactECharts from "echarts-for-react";
function InteractiveChart() {
const handleChartClick = (params, instance) => {
console.log('Chart clicked:', params);
};
const handleChartReady = (instance) => {
console.log('Chart ready:', instance);
// Direct ECharts API access
instance.on('mouseover', (params) => {
console.log('Mouse over:', params);
});
};
const onEvents = {
'click': handleChartClick,
'legendselectchanged': (params) => console.log('Legend changed:', params)
};
return (
<ReactECharts
option={chartOption}
onEvents={onEvents}
onChartReady={handleChartReady}
style={{ height: '400px' }}
/>
);
}import React, { useState } from "react";
import ReactECharts from "echarts-for-react";
import * as echarts from "echarts";
// Register custom theme
echarts.registerTheme('my_theme', {
backgroundColor: '#f4f4f4',
textStyle: { color: '#333' }
});
function ThemedChart() {
const [loading, setLoading] = useState(true);
React.useEffect(() => {
// Simulate data loading
setTimeout(() => setLoading(false), 2000);
}, []);
return (
<ReactECharts
option={chartOption}
theme="my_theme"
showLoading={loading}
loadingOption={{
text: 'Loading...',
color: '#4d90fe',
textColor: '#000'
}}
style={{ height: '400px' }}
/>
);
}import React from "react";
import ReactECharts from "echarts-for-react";
function ResponsiveChart() {
return (
<ReactECharts
option={chartOption}
style={{ width: '100%', height: '50vh' }}
opts={{
renderer: 'svg', // Use SVG renderer
width: 'auto',
height: 'auto'
}}
autoResize={true}
/>
);
}import React, { useRef, useEffect } from "react";
import ReactECharts from "echarts-for-react";
function ChartWithInstanceAccess() {
const chartRef = useRef<InstanceType<typeof ReactECharts>>(null);
useEffect(() => {
if (chartRef.current) {
const instance = chartRef.current.getEchartsInstance();
// Export chart as image
const dataURL = instance.getDataURL({
type: 'png',
pixelRatio: 2,
backgroundColor: '#fff'
});
// Manually trigger resize
instance.resize();
// Add custom event listeners
instance.on('finished', () => {
console.log('Chart render finished');
});
}
}, []);
return (
<ReactECharts
ref={chartRef}
option={chartOption}
style={{ height: '400px' }}
/>
);
}import React from "react";
import ReactECharts from "echarts-for-react";
function ConditionalUpdateChart({ data, updateTrigger }) {
const shouldSetOption = (prevProps, props) => {
// Only update chart when specific conditions are met
return props.updateTrigger !== prevProps.updateTrigger;
};
return (
<ReactECharts
option={generateOption(data)}
shouldSetOption={shouldSetOption}
notMerge={true}
replaceMerge={['series']}
lazyUpdate={false}
style={{ height: '400px' }}
/>
);
}