useECharts

React hook that owns the chart lifecycle while you own the container markup

Overview

useECharts is a hook primitive that drives the same lifecycle as <EChartsReact> (init, option updates, event binding, resize, teardown) but lets you render the container <div>. Reach for it when the component’s fixed container gets in the way — for example, when nesting the chart in a styled card with a toolbar, swapping in a skeleton loader, or composing the chart with surrounding layout you’d rather control directly.

import { useECharts } from 'react-echarts-library';         // full bundle
import { useECharts } from 'react-echarts-library/core';    // tree-shakeable

Added in v1.4.0.

Signature

function useECharts(
  echarts: EChartsCore,
  options: UseEChartsOptions
): {
  containerRef: (node: HTMLDivElement | null) => void;
  getInstance: () => EChartsType | null;
};
ArgumentTypeDescription
echartsEChartsCoreThe echarts instance. From the full bundle, pass echarts (it satisfies the shape). From react-echarts-library/core, pass your tree-shaken echarts/core import.
optionsUseEChartsOptionsSame shape as EChartsReactProps minus the container-level props (style, className, HTML attrs) — those belong on your own div.

UseEChartsOptions accepts: option, theme, opts, onEvents, notMerge, replaceMerge, lazyUpdate, showLoading, loadingOption, shouldSetOption, autoResize, onChartReady. See the Props Reference for each field.

Return value

FieldTypeDescription
containerRef(node) => voidCallback ref. Attach to your container <div>. The hook initializes the chart when the node mounts and disposes on unmount.
getInstance() => ECharts | nullImperative accessor for the underlying ECharts instance. Returns null before mount and after unmount.

Minimal Usage

import { useECharts } from 'react-echarts-library/core';
import * as echarts from 'echarts/core';
import { BarChart } from 'echarts/charts';
import { GridComponent, TooltipComponent } from 'echarts/components';
import { CanvasRenderer } from 'echarts/renderers';

echarts.use([BarChart, GridComponent, TooltipComponent, CanvasRenderer]);

function MyChart() {
  const { containerRef } = useECharts(echarts, {
    option: {
      xAxis: { type: 'category', data: ['A', 'B', 'C'] },
      yAxis: { type: 'value' },
      series: [{ type: 'bar', data: [10, 20, 30] }],
    },
  });

  return <div ref={containerRef} style={{ height: 320 }} />;
}

Imperative Toolbar

Use getInstance to dispatch ECharts actions from your own UI:

import { useECharts, exportToPNG } from 'react-echarts-library';
import * as echarts from 'echarts';

function ChartCard() {
  const { containerRef, getInstance } = useECharts(echarts, { option });

  const handleZoomIn = () => {
    getInstance()?.dispatchAction({ type: 'dataZoom', start: 20, end: 80 });
  };

  const handleExport = () => {
    const chart = getInstance();
    if (chart) exportToPNG(chart, { filename: 'chart.png' });
  };

  return (
    <section className="card">
      <header className="card-header">
        <h3>Quarterly Revenue</h3>
        <div className="card-actions">
          <button onClick={handleZoomIn}>Focus middle</button>
          <button onClick={handleExport}>Download PNG</button>
        </div>
      </header>
      <div ref={containerRef} style={{ height: 320 }} />
    </section>
  );
}

Loading Skeleton Swap

The hook returns a callback ref, so you can mount the chart only after data is ready and render a skeleton in its place beforehand:

function AsyncChart({ data, isLoading }) {
  const { containerRef } = useECharts(echarts, {
    option: { /* derived from data */ },
  });

  if (isLoading) {
    return <div className="skeleton" style={{ height: 320 }} />;
  }
  return <div ref={containerRef} style={{ height: 320 }} />;
}

Reacting to External State

Combine with useChartTheme to react to OS dark-mode changes, or any other React state, without re-implementing the lifecycle:

import { useECharts, useChartTheme } from 'react-echarts-library';
import * as echarts from 'echarts';

function ThemedChart({ data }) {
  const theme = useChartTheme();
  const { containerRef } = useECharts(echarts, {
    theme,
    option: {
      xAxis: { type: 'category', data: data.labels },
      yAxis: { type: 'value' },
      series: [{ type: 'line', data: data.values }],
    },
  });

  return <div ref={containerRef} style={{ height: 320 }} />;
}

Typed Events

Pair with EChartsEventsMap for IDE completion on event names:

import { useECharts } from 'react-echarts-library';
import type { EChartsEventsMap } from 'react-echarts-library';

const handlers: EChartsEventsMap = {
  click: (params) => console.log('clicked:', params),
  legendselectchanged: (params) => console.log('legend:', params),
};

function TypedChart() {
  const { containerRef } = useECharts(echarts, { option, onEvents: handlers });
  return <div ref={containerRef} style={{ height: 320 }} />;
}

When to Use the Hook vs the Component

Use caseRecommended
Drop a chart into a layout<EChartsReact> / <EChartsCore>
Render a styled card around the chartuseECharts
Swap a skeleton in for the chart containeruseECharts
Position a toolbar that talks to the instanceEither — useECharts is one less ref hop
Share the lifecycle across non-chart UIuseECharts

The component is implemented on top of the hook, so neither path costs more than the other at runtime.

See Also