tech-book-labs
可視化(チャート / 図 / 表) · 最終検証 2026-09-01 · echarts 6.1.0 · 初公開 2026-09-01

ECharts v6 を React で使う

Apache ECharts v6 を React で動かす最小構成。echarts/core + use() の tree-shaking 登録、init / dispose のライフサイクル、setOption の merge / notMerge / replaceMerge の違い(実測)、コンテナ幅に追従しない resize の仕様、Node での SSR(SVG 文字列出力)まで。option JSON を書き換えて試せるプレイグラウンド demo 付き。

echarts chart visualization react canvas

検証日: 2026-09-01

使用バージョン: echarts@6.1.0(React 19・ラッパー無し)

対象: ECharts を React に組み込みたい / setOption したのに前の系列が残る・リサイズで崩れる現象に当たった場面

Apache ECharts v6 を ラッパーライブラリ無しで React に組み込む最小構成。option(グラフ定義オブジェクト)を直接書き換えて挙動を確かめられるプレイグラウンドと、setOption の merge 挙動・リサイズの仕様を実測で確認します。

触って試す

左の option JSON がそのまま ECharts への入力。preset を切り替える → data の数値を書き換える → series の type を "bar" から "line" に変える、のように試しながら読み進められる。notMerge チェックは後述の merge 挙動の実験用。

なぜ ECharts か(Chart.js / Recharts との位置取り)

  • ECharts: option オブジェクト 1 個にグラフ定義を全部書く宣言スタイル。チャート種類・コンポーネント(dataZoom / visualMap 等)の品揃えが最も広く、フレームワーク非依存
  • Chart.js: 同じ canvas + 設定スタイルだが、より軽量・シンプル寄り。定番チャートだけなら十分
  • Recharts: JSX でグラフを合成する React 専用スタイル

「地図・ヒートマップ・ズーム連動のような込み入った可視化までいく可能性があるか」が ECharts を選ぶ分かれ目。

最小サンプル(echarts/core + use() 登録)

npm i echarts
項目
検証バージョンecharts@6.1.0
React ラッパー不要(本記事は素の echarts。echarts-for-react は最終更新が古く v6/React 19 での動作保証がない)
TypeScript 型本体同梱
描画方式canvas / SVG 選択式

import * as echarts from "echarts" でも動くが、全チャート・全コンポーネントがバンドルに入る。echarts/core から使う部品だけ use() で登録するのが公式推奨の tree-shaking 構成:

import * as echarts from "echarts/core";
import { BarChart } from "echarts/charts";
import { GridComponent, TooltipComponent, LegendComponent } from "echarts/components";
import { CanvasRenderer } from "echarts/renderers";

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

登録が足りない部品を option で使うと、グラフがエラーではなく無描画または部分欠けになる(tooltip が出ない、軸が出ない等)。Chart.js の register は明示的なエラーで落ちるのと対照的に、ECharts は静かに欠けるので気づきにくい。

React への組み込み: init と dispose のライフサイクル

ECharts は DOM 要素に自分でインスタンスを張り付ける設計なので、React では useRef + useEffect で管理する。次のコードが「マウントで init、アンマウントで dispose」の基本形:

function Chart({ option }: { option: echarts.EChartsCoreOption }) {
  const divRef = useRef<HTMLDivElement>(null);
  const chartRef = useRef<echarts.ECharts | null>(null);

  useEffect(() => {
    if (!divRef.current) return;
    const chart = echarts.init(divRef.current);
    chartRef.current = chart;
    return () => chart.dispose();   // cleanup で必ず破棄
  }, []);

  useEffect(() => {
    chartRef.current?.setOption(option);  // option 更新は setOption で
  }, [option]);

  return <div ref={divRef} style={{ width: "100%", height: 300 }} />;
}

cleanup の dispose() を書かないと、React 18+ の StrictMode(開発時に effect を 2 回実行して掃除漏れを炙り出す仕組み)で同じ div に 2 回 init が走り、コンソールに警告が出る:

There is a chart instance already initialized on the dom.

なお dispose() 済みインスタンスへの setOption は throw せず、警告(Instance ec_xxx has been disposed)を出して無視される(実測)。エラーで落ちない分、「更新したのに描画されない」という形で現れる。

setOption の merge 挙動 — 前の系列が残る理由

setOption は既定で merge(差分マージ)。2 系列のグラフに 1 系列だけの option を渡しても、2 本目は消えずに残る。実測:

chart.setOption({ series: [s1, s2] });          // 2 本描画
chart.setOption({ series: [s1改] });            // → series は 2 本のまま(s2 が残る)
chart.setOption({ series: [s1改] }, { notMerge: true });  // → 1 本になる(全置換)
chart.setOption({ series: [s1改] }, { replaceMerge: ["series"] }); // → series だけ置換

使い分けの目安:

方法挙動向く場面
既定(merge)渡したキーだけ差分更新データ値の更新、色の変更
notMerge: trueoption 全体を破棄して置換グラフの種類ごと切り替える
replaceMerge: ["series"]指定キーだけ置換、他は維持系列の増減(軸や tooltip 設定は保持)

冒頭のプレイグラウンドで再現できる: preset: bar(2 系列)を適用 → JSON の series を 1 本に減らして「setOption を実行」。notMerge OFF なら 2 本目が残り、ON にすると消える。

リサイズはコンテナに追従しない

ECharts の canvas は init 時点のコンテナ寸法で固定され、その後コンテナの幅が変わっても自動では追従しない。chart.resize() を呼んだ瞬間だけ現在の寸法に合わせ直す。スライダーで体感できる:

実務では window の resize イベントか、ResizeObserver(要素自体の寸法変化を監視できるブラウザ API)で resize() を呼ぶ:

const ro = new ResizeObserver(() => chart.resize());
ro.observe(divRef.current);
// cleanup で ro.disconnect()

フレックスレイアウト内でサイドバーの開閉だけで幅が変わるケースは window resize では拾えないので、ResizeObserver の方が確実。

Node での SSR(SVG 文字列出力)

v5.3 以降、DOM の無い Node 環境で SVG 文字列としてレンダリングできる。OG 画像やメール向けの静的グラフ生成に使える(実測: 3.9KB の SVG が返る):

const chart = echarts.init(null, null, {
  renderer: "svg", ssr: true, width: 400, height: 300,
});
chart.setOption(option);
const svgStr = chart.renderToSVGString();  // "<svg width=..." の文字列

本記事の merge 挙動の実測も、この SSR モードを使って Node 単体で行った(ブラウザ不要でテストに組み込める)。

つまずいたポイント

  • 系列を減らしたのに描画が減らない — 既定 merge の仕様。notMerge: truereplaceMerge: ["series"] を明示する(本記事の表を参照)
  • There is a chart instance already initialized on the dom. — 同じ div への二重 init。React では effect cleanup の dispose() 漏れが典型原因(StrictMode で顕在化する)
  • 部品の登録漏れが「エラーにならない」echarts/core 構成で tooltip や legend が出ない時は、まず use([...]) に該当 Component があるか確認。エラーメッセージ頼みのデバッグができない
  • dispose() 後の setOption が黙って無視される — 非同期処理の完了後に更新するコードでは、アンマウント済みかを chart.isDisposed() で確認してから呼ぶ
  • プレイグラウンドの option を JSON にする制約 — 本物の option は関数(formatter 等)も書けるが、demo は JSON.parse なので関数は書けない。関数が要る設定を試す時はコードに移す

関連書籍

tech-book.net /books/9784254122589

Python インタラクティブ・データビジュアライゼーション入門 : Plotly/Dashによるデータ可視化とWebアプリ構築 | tech-book.net

@driller/小川 英幸/古木 友子 · 朝倉書店

Webサイトで公開できる対話的・探索的(読み手が自由に動かせる)可視化をPythonで実践.デー

この本が役立つ理由 — ECharts が守備範囲とする「ズーム・連動・ダッシュボード」型のインタラクティブ可視化を、Plotly/Dash 側から体系的に学べる。option の引き出しを増やす発想源に
詳細を tech-book.net で見る
tech-book.net /books/9784798163970

データ分析者のためのPythonデータビジュアライゼーション入門 コードと連動してわかる可視化手法 | tech-book.net

小久保 奈都弥 · 翔泳社

分析したデータを わかりやすく ビジュアライゼーションしよう! 【データビジュアライゼーションとは】 数値データ・位置のデータ・文章のデータ等

この本が役立つ理由 — グラフの手前の「分析としてどう切るか」を、コードと連動した図で確認しながら進める入門。プレイグラウンドで試す option の中身(何をどの軸に置くか)が決めやすくなる
詳細を tech-book.net で見る

関連記事 / 関連 Topic