Chart.js v4 を React で使う
Chart.js v4 + react-chartjs-2 の最小構成。v3 以降必須になった register の仕組みと「category is not a registered scale」エラーの原因、bar/line の動的切替、tooltip callback での単位付与、responsive 設定の親要素の高さ問題まで、動く demo で確認する。
検証日: 2026-08-31
使用バージョン:
chart.js@4.5.1+react-chartjs-2@5.3.1(React 19)対象: React で Chart.js を使い始めて「
"category" is not a registered scale」で詰まった / v2 時代の記事のコードが動かない場面
Chart.js v4 を React で動かす最小構成。v3 以降で必須になった register(使う部品の事前登録)の仕組みと、初見でほぼ全員が踏むエラーの原因、bar / line の動的切替、tooltip のカスタマイズまでを動く demo で確認します。
触って試す
ボタンでグラフ種別(bar / line)の切替と、2 系列目の表示 / 非表示ができる。凡例(グラフ上部のラベル)クリックでも系列を toggle できる — これは Chart.js 標準の Legend の挙動で、コードは書いていない。
なぜ Chart.js か(Recharts / D3 との位置取り)
- Chart.js:
<canvas>描画。設定オブジェクトを渡すスタイルで、React 以外(Vue / vanilla / サーバーサイド)でも同じ知識が使える。データ点が多くても DOM が増えない - Recharts: SVG + React コンポーネント合成。JSX でグラフを組みたい・要素を CSS で触りたいなら向く
- D3: 描画プリミティブから自作。定型チャートには過剰
「よくある形のグラフを、設定を書いて済ませたい」が Chart.js の守備範囲。
最小サンプル(npm 2 つ / register が必須)
npm i chart.js react-chartjs-2
| 項目 | 値 |
|---|---|
| 検証バージョン | chart.js@4.5.1 / react-chartjs-2@5.3.1 |
| react-chartjs-2 の peer 要件 | chart.js ^4.1.1、React 16.8〜19 |
| TypeScript 型 | 両方とも本体同梱 |
| 描画方式 | <canvas>(SVG ではない) |
次のコードが「棒グラフを 1 つ出す」最小構成。ポイントは import した部品を ChartJS.register(...) に並べること:
import {
Chart as ChartJS,
CategoryScale, // x 軸(カテゴリ軸)
LinearScale, // y 軸(数値軸)
BarElement, // 棒
Tooltip,
Legend,
} from "chart.js";
import { Bar } from "react-chartjs-2";
ChartJS.register(CategoryScale, LinearScale, BarElement, Tooltip, Legend);
export function Sales() {
return (
<Bar
data={{
labels: ["4月", "5月", "6月"],
datasets: [{ label: "売上", data: [120, 190, 150] }],
}}
/>
);
}
「category is not a registered scale」の正体
register を書き忘れる(または部品が足りない)と、実行時にこのエラーで止まる:
Error: "category" is not a registered scale.
原因は v3 で入った tree-shaking(使わないコードをバンドルから落とす仕組み)対応。Chart.js 本体は軸・要素・プラグインをすべて分割していて、register したものだけが実行時に使える。v2 時代の記事のコードが動かないのは大半これ。
部品の対応は覚えるより「エラーメッセージに出た名前を import に足す」で解決できる:
| エラーに出る名前 | register する部品 |
|---|---|
"category" is not a registered scale | CategoryScale |
"linear" is not a registered scale | LinearScale |
"bar" is not a registered element | BarElement |
"bar" is not a registered controller | BarController(汎用 <Chart> 使用時。後述) |
"line" 系 | LineElement + PointElement + LineController |
"arc" 系(円グラフ) | ArcElement + DoughnutController など |
bar / line を動的に切り替える
demo のグラフ種別切替は、react-chartjs-2 の型固定コンポーネント(<Bar> / <Line>)ではなく 汎用 <Chart> に type を渡す形で実装している。data と options はそのまま、type だけ state で差し替える:
import { Chart } from "react-chartjs-2";
const [type, setType] = useState<"bar" | "line">("bar");
<Chart type={type} data={data} options={options} />
ここに v4 の register のもう 1 段がある。型付きコンポーネント(<Bar> / <Line>)は対応する Controller(チャート種別ごとの制御ロジック)を自動で register するが、汎用 <Chart> は何も自動登録しない。scale と element を全部並べても、Controller が無いと実行時にこう落ちる(検証時に実際に踏んだ):
"bar" is not a registered controller.
汎用 <Chart> で bar / line を切り替えるなら register は次の 9 点セットになる:
ChartJS.register(
CategoryScale, LinearScale, // 軸
BarElement, LineElement, PointElement, // 描画要素
BarController, LineController, // チャート種別の制御(汎用 <Chart> では必須)
Tooltip, Legend,
);
tooltip callback で単位を付ける
tooltip(ホバー時の吹き出し)の表示は plugins.tooltip.callbacks.label で 1 行ずつ差し替えられる。次のコードは値に「万円」「人」の単位を付ける例:
const options = {
plugins: {
tooltip: {
callbacks: {
label: (ctx) =>
`${ctx.dataset.label}: ${ctx.parsed.y.toLocaleString("ja-JP")} 万円`,
},
},
},
};
ctx.parsed.y が数値(パース済みの値)、ctx.dataset が系列定義。raw ではなく parsed を使うと軸の型が変わっても壊れにくい。
responsive とコンテナの高さ
Chart.js は既定で responsive: true だが、maintainAspectRatio: true(既定)のままだと幅から高さが自動決定され、親の高さ指定が効かない。高さを自分で管理する場合は両方セットで:
const options = { responsive: true, maintainAspectRatio: false };
<div style={{ height: 280 }}>
<Chart type="bar" data={data} options={options} />
</div>
demo もこの形(height: 280 の div で包む)。maintainAspectRatio: false を付けずに親に高さだけ指定すると、リサイズのたびにグラフが縦に伸び続ける古典的な症状が出る。
つまずいたポイント
"category" is not a registered scale— register 忘れ。本記事の対応表どおり import に足す。エラー文字列に部品名がそのまま出るので、それを手掛かりにするのが早い"bar" is not a registered controller— 型付き<Bar>から汎用<Chart type="bar">に書き換えた瞬間に出た。Controller の自動登録は型付きコンポーネントだけの挙動で、汎用<Chart>ではBarController/LineControllerを自分で register する- line は
LineElementだけでは動かない — 線上の点が別部品(PointElement)になっている - tooltip callback の型 — TypeScript で
ctxを厳密に型付けするならTooltipItem<"bar">を使う。demo では bar / line 両対応のため必要フィールド(dataset.label/parsed.y)だけの構造型で受けた - React 19 +
react-chartjs-2@5.3.1は peer 警告なしで動いた — peerDependencies が React 19 を明示的に含む(^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0) - SSR(Astro の prerender)では描画できない —
<canvas>前提なので、demo はclient:only="react"で クライアント描画のみにしている。client:loadだとサーバー側レンダリングで落ちる構成もあるため、canvas 系はまずclient:onlyが安全
関連書籍
Python と JavaScriptではじめるデータビジュアライゼーション | tech-book.net
Webからデータを取得して整理・分析し可視化するまで一連の流れがわかる! 本書はデータ可視化データフローを最初から終わりまでカバーし
データビジュアライゼーションのためのデザイン原則 : 日常的に扱うデータを効果的に伝わる情報に変える | tech-book.net
「データ理解から配色やフォントなどのデザインの基礎、ダッシュボード設計まで丁寧にときほぐした、データ可視化を学
関連記事 / 関連 Topic
- Recharts v3 の bar chart レシピ — SVG + JSX 派の選択肢
- D3 + React で bar chart — 描画を完全に自作する場合
- 体系的に学ぶなら: JavaScript の本 / TypeScript の本(tech-book.net)