0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Recharts】React で最も “React らしく書ける” グラフライブラリ

Last updated at Posted at 2025-11-20

【Recharts】React で最も “React らしく書ける” グラフライブラリ

シンプル版とゴリゴリ版の 2 パターンで徹底解説

React でグラフを描くときに人気のライブラリ Recharts
この記事では、Recharts の特徴を

  • シンプル版(Basic)
  • ゴリゴリ版(Advanced)

の 2 パターンのグラフを使ってわかりやすく紹介します。


📂 GitHub リポジトリ

この記事で紹介しているコードは、以下のリポジトリにまとめています。

 構成例(Next.js + TypeScript)の一部:

  • src/data.ts
  • src/components/RechartsExample.tsx
  • src/components/NivoExample.tsx
  • src/components/ChartJsExample.tsx
  • src/components/ApexExample.tsx

🖼 グラフのスクリーンショット

記事内でイメージしやすいように、実際に描画したグラフのスクリーンショットも貼っておきます。

スクリーンショット 2025-11-21 6.35.29.png


📘 Recharts とは?

Recharts は React コンポーネント構成のチャートライブラリです。

  • JSX で直感的に記述できる
  • 合成チャート(Line + Bar + Area)が簡単
  • TypeScript との相性も良い
  • 管理画面やダッシュボードでよく使われる

📦 インストール

npm install recharts

📊 記事で使用する共通データ

この記事とサンプルコードでは、実績値と目標値の 2 系列を持つデータを共通で使います。

// src/data.ts

export type ChartDatum = {
  month: string;
  actual: number; // 実績値
  target: number; // 目標値
};

export const chartData: ChartDatum[] = [
  { month: "Jan", actual: 120, target: 150 },
  { month: "Feb", actual: 210, target: 200 },
  { month: "Mar", actual: 160, target: 220 },
  { month: "Apr", actual: 280, target: 250 },
  { month: "May", actual: 300, target: 260 },
];

RechartsExample コンポーネントの全体像

ここからが本題です。

1 つのコンポーネント RechartsExample の中で、

  • 上段に「Simple Recharts(シンプルな LineChart)」
  • 下段に「Recharts Advanced(コンポーネント合成&カスタム Tooltip)」
    という 2 つのグラフを並べています。
    コード全体は次のとおりです。
// src/components/RechartsExample.tsx
import {
  ResponsiveContainer,
  LineChart,
  Line,
  XAxis,
  YAxis,
  CartesianGrid,
  Tooltip,
  Legend,
  ComposedChart,
  Bar,
  ReferenceLine,
  Area,
} from "recharts";
import { chartData } from "../data";

// Recharts の TooltipProps 型に依存しない、自前のシンプルな型
type CustomTooltipProps = {
  active?: boolean;
  label?: string;
  payload?: {
    value: number;
    dataKey?: string;
    name?: string;
    color?: string;
  }[];
};

function CustomTooltip({ active, label, payload }: CustomTooltipProps) {
  if (!active || !payload || payload.length === 0) return null;

  return (
    <div
      style={{
        background: "white",
        border: "1px solid #e5e7eb",
        borderRadius: 8,
        padding: 8,
        fontSize: 12,
      }}
    >
      <div style={{ marginBottom: 4, fontWeight: 600 }}>{label}</div>
      {payload.map((item) => (
        <div
          key={item.dataKey ?? item.name}
          style={{ color: item.color ?? "#111827" }}
        >
          {item.name}: {item.value}
        </div>
      ))}
    </div>
  );
}

export function RechartsExample() {
  // 目標の平均値(ReferenceLine 用)
  const avgTarget =
    chartData.reduce((sum, d) => sum + d.target, 0) / chartData.length;

  return (
    <div style={{ display: "grid", gap: 24 }}>
      {/* シンプル版 */}
      <section>
        <h2
          style={{
            fontSize: 14,
            fontWeight: 600,
            marginBottom: 8,
            color: "#4b5563",
          }}
        >
          Simple Recharts(素直な LineChart)
        </h2>
        <p
          style={{
            fontSize: 12,
            color: "#6b7280",
            marginBottom: 12,
          }}
        >
          JSX でコンポーネントを組み合わせる、基本的な Recharts の使い方です。
          実績と目標の 2 系列をシンプルな折れ線グラフで表現しています。
        </p>
        <div
          style={{
            height: 260,
            borderRadius: 12,
            background: "#ffffff",
            boxShadow: "0 8px 24px rgba(15,23,42,0.06)",
            padding: 12,
          }}
        >
          <ResponsiveContainer width="100%" height="100%">
            <LineChart data={chartData}>
              <CartesianGrid strokeDasharray="4 4" stroke="#e5e7eb" />
              <XAxis dataKey="month" />
              <YAxis />
              <Tooltip />
              <Legend />
              <Line
                type="monotone"
                dataKey="actual"
                name="実績"
                stroke="#3b82f6"
                strokeWidth={2}
                dot={{ r: 4 }}
              />
              <Line
                type="monotone"
                dataKey="target"
                name="目標"
                stroke="#9ca3af"
                strokeWidth={2}
                strokeDasharray="6 4"
                dot={{ r: 0 }}
              />
            </LineChart>
          </ResponsiveContainer>
        </div>
      </section>

      {/* Recharts ガチガチ版(コンポーネント合成を強調) */}
      <section>
        <h2
          style={{
            fontSize: 14,
            fontWeight: 600,
            marginBottom: 8,
            color: "#4b5563",
          }}
        >
          Recharts Advanced(コンポーネント合成 & カスタム Tooltip)
        </h2>
        <p
          style={{
            fontSize: 12,
            color: "#6b7280",
            marginBottom: 12,
          }}
        >
          Bar / Line / Area / ReferenceLine / カスタム Tooltip
          など、Recharts の「コンポーネントを組み合わせて作る」強みを活かした例です。
          同じデータでも、構成を変えるだけでダッシュボードらしい表現になります。
        </p>
        <div
          style={{
            height: 260,
            borderRadius: 12,
            background:
              "linear-gradient(135deg, rgba(248,250,252,1), rgba(226,232,240,1))",
            boxShadow: "0 18px 40px rgba(148,163,184,0.45)",
            padding: 14,
          }}
        >
          <ResponsiveContainer width="100%" height="100%">
            <ComposedChart data={chartData}>
              <CartesianGrid
                strokeDasharray="3 3"
                stroke="rgba(148,163,184,0.6)"
              />
              <XAxis dataKey="month" tick={{ fill: "#4b5563", fontSize: 11 }} />
              <YAxis tick={{ fill: "#4b5563", fontSize: 11 }} />
              <Tooltip content={<CustomTooltip />} />
              <Legend />
              {/* 目標平均のガイドライン */}
              <ReferenceLine
                y={avgTarget}
                stroke="#f97316"
                strokeDasharray="4 4"
                label={{
                  value: "目標平均",
                  position: "insideTopRight",
                  fill: "#f97316",
                  fontSize: 11,
                }}
              />
              {/* 実績の棒グラフ */}
              <Bar
                dataKey="actual"
                name="実績(Bar)"
                barSize={26}
                fill="#3b82f6"
                radius={[6, 6, 0, 0]}
              />
              {/* 目標のライン(ガイド的役割) */}
              <Line
                type="monotone"
                dataKey="target"
                name="目標(Line)"
                stroke="#111827"
                strokeWidth={2}
                strokeDasharray="5 4"
                dot={{ r: 3 }}
              />
              {/* 実績の Area(ふんわりトレンドを見せる) */}
              <Area
                type="monotone"
                dataKey="actual"
                name="実績トレンド"
                stroke="none"
                fill="rgba(59,130,246,0.15)"
              />
            </ComposedChart>
          </ResponsiveContainer>
        </div>
      </section>
    </div>
  );
}

Simple Recharts(上段)の解説

上段の「Simple Recharts」は、Recharts の基本をそのまま示す構成です。

  • LineChart に Line を 2 本載せるだけのシンプルな折れ線グラフ
  • 実績(actual)は青色の実線、目標(target)はグレーの破線で表現
  • 軸やグリッド、Tooltip、Legend は最小限の設定

ポイントは次の通りです。

  • JSX の構造を見れば、グラフ構造がそのまま理解できる
  • 系列を増やしたければ を足していけばよい
  • CSS 的な props(stroke, strokeDasharray, dot など)が直感的

「まず Recharts を触ってみる」ための入門サンプルとしてちょうどよい形です。

Recharts Advanced(下段)の解説

下段の「Recharts Advanced」は、Recharts の強みを活かした“ゴリゴリ版”です。

  • ComposedChart を使って、Bar / Line / Area を合成
  • ReferenceLine で目標平均のガイドラインを表示
  • カスタム Tooltip コンポーネントで表示内容と見た目を制御
  • 背景やグリッドの色・影・余白で「ダッシュボード感」を演出
    特に注目したいポイントは次の通りです。

1.合成チャート

<Bar ... />
<Line ... />
<Area ... />

を同じ ComposedChart の中に共存させることで、

  • 実績の「量」(Bar)
  • 実績の「トレンド」(Area)
  • 目標の「ライン」(Line)
    を一つのグラフで同時に見せています。

2.ReferenceLine による平均ライン

const avgTarget =
  chartData.reduce((sum, d) => sum + d.target, 0) / chartData.length;

<ReferenceLine
  y={avgTarget}
  stroke="#f97316"
  ...
/>

で、「目標の平均」を一目で分かるようにしています。
実務では「このラインを上回っているかどうか」を示したい場面が多く、
こうした視覚的なガイドを簡単に載せられるのは Recharts の強みです。

3.カスタム Tooltip
CustomTooltip コンポーネントを定義し、Tooltip の content に渡すことで、

  • 表示レイアウト
  • 文字色
  • 枠線・角丸
    を細かく調整しています。
    Recharts の Tooltip 用型に直接依存していないので、TypeScript エラーを避けやすい形にもなっています。

🧩 Recharts のメリット・デメリット

Recharts を使ってみて、実際の現場でも採用される理由・採用されにくい理由を整理すると次のようになります。


✅ メリット(強み)

1. React コンポーネントとして直感的に書ける

JSX の入れ子構造がそのままグラフ構造になります。

UI と同じ感覚で <LineChart><Line /></LineChart> という形で組み立てられるため、
React 開発者にとって最も自然なグラフライブラリです。


2. ComposedChart による複合グラフが強すぎる

Bar / Line / Area / ReferenceLine のような複合表現が極めて簡単。

実務でよくある
「量(Bar)+ トレンド(Area)+ 指標ライン(ReferenceLine)」
といった構成を JSX で自然に書けるのは Recharts の大きな強みです。


3. TypeScript との相性が良い

コンポーネントベースの API なので、
プロップスの型が自動補完され、型安全に実装できます。

企業内のダッシュボード開発にも採用されやすいです。


4. カスタマイズ性が非常に高い

  • 軸デザイン
  • グリッド
  • カスタム Tooltip
  • 点の形状
  • 塗りのスタイル
  • コンポーネント合成

など、見た目を細かくコントロールできます。

デザインを UI 全体に合わせたい時に最も強いのが Recharts です。


⚠️ デメリット(弱み)

1. デフォルトのデザインは “普通”

Nivo のような「最初から美しいチャート」ではありません。
ブランドカラーに寄せたい場合は、ある程度の調整が必要です。


2. 設定オブジェクト派には合わない

Chart.js や ApexCharts のような
「設定オブジェクトを渡すスタイル」ではなく、

グラフを JSX で組み立てるスタイルです。

好みが分かれる部分です。


3. 高度なアニメーションは苦手

Nivo や D3 ほどアニメーションの表現力は強くありません。
“魅せるグラフ” を作りたい場合は別ライブラリのほうが適しています。


🎯 Recharts を選ぶべきケース

Recharts が特にフィットする場面は次のとおりです。

  • React/TypeScript を中心とした管理画面や業務ダッシュボード
  • 複合チャートを自然に実装したい
  • UI/UX を React コンポーネントで統一したい
  • 保守性を重視するプロジェクト

逆に、
「最初からおしゃれなデザインが欲しい」場合は Nivo、
「設定オブジェクトで直感的に作りたい」場合は Chart.js/ApexCharts が向いています。


📝 まとめ

この記事では Recharts を

  • Simple Recharts(素直な LineChart)
  • Recharts Advanced(Bar / Line / Area / ReferenceLine / カスタム Tooltip)

の 2 つのチャートで比較しながら、その特徴を整理しました。

Recharts の本質は “コンポーネント合成のしやすさ” にあります。

React の UI と同じ考え方でチャートを組み立てたい場合、
Recharts は非常に強力な選択肢になります。

👉 Nivo 編」です。
https://qiita.com/kz2021019/items/67c3bd727a1eb35e8c4c

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?