🤖

【React】react-chartjs-2 使い方まとめ

2022/11/23に公開1

概要

世の中にはchart.jsの記事はたくさんあるのにchart-js2の記事は全然ない(多分)ので書きました。
あとクラスコンポーネントで書いてる記事はあるのに関数コンポーネントで書いてる記事はなかったり(多分)
なのでこの記事では関数コンポーネントを使って棒グラフと棒グラフ+折れ線の2軸グラフを紹介します。

pluginの解説は以下別記事にしてます
zoomとpan(chartjs-plugin-zoom)

import

まずはimport内容です。
react-chartjs-2はchart.jsも必要です(chart.jsのv4かv3にしか対応してないのでバージョンに注意しましょう。
https://react-chartjs-2.js.org/

npm install --save chart.js react-chartjs-2

棒グラフ

棒グラフ作った時のバージョンは以下です。
"chart.js": "3.9.1",
"react": "18.2.0",
"react-chartjs-2": "4.3.1",

https://codesandbox.io/s/react-chartjs-2-vertical-bar-2kvrj0?file=/src/ChartBar.jsx

ただグラフを作るだけなら簡単でreact-chartjs-2のサイトにサンプルがあるのでそれを参考にしましょう(但しサンプルはtypescript)。私が書いたコードもほとんどこれと同じです。
https://react-chartjs-2.js.org/examples/vertical-bar-chart

コード解説

import

import内容は基本的にサンプルコピペでOKです。
import { Bar } from "react-chartjs-2";のとこは棒グラフなのでBarになっててグラフの種類によってimport内容が変わります。(折れ線グラフだとLine)

import React from "react";
import {
  Chart as ChartJS,
  CategoryScale,
  LinearScale,
  BarElement,
  Title,
  Tooltip,
  Legend
} from "chart.js";
import { Bar } from "react-chartjs-2";

ChartJS.register(
  CategoryScale,
  LinearScale,
  BarElement,
  Title,
  Tooltip,
  Legend
);

データとオプション

optionに関しては説明してるときりがないのでcodesandboxでいじって確認するか公式を確認しましょう。
コードの最後の方にreturn <Bar options={options} data={data} />;とあるようにoptionsとdataの設定をするとグラフが作成されます。
dataのdatasetsは配列になっていて1つの要素が1つの凡例に対応してます。

const options = {
  responsive: true,
  plugins: {
    legend: {
      position: "top"
    },
    title: {
      display: true,
      text: "Chart.js Bar Chart"
    }
  }
};

const labels = ["January", "February", "March", "April", "May", "June", "July"];
const data1 = [12, 11, 14, 52, 14, 32, 36];
const data2 = [22, 31, 17, 32, 24, 62, 66];

const data = {
  labels, // x軸のラベルの配列
  datasets: [
    {
      label: "Dataset 1", // 凡例
      data: data1,        // データの配列(labelsと要素数同じ)
      backgroundColor: "rgba(255, 99, 132, 0.5)" // グラフの棒の色
    },
    {
      label: "Dataset 2",
      data: data2,
      backgroundColor: "rgba(53, 162, 235, 0.5)"
    }
  ]
};

export const ChartBar = () => {
  return <Bar options={options} data={data} />;
};

2軸グラフ(棒+折れ線)

次は2軸グラフの解説をします。ただこれも簡単でreact-chartjs-2のサイトにサンプルがあるのでそれを参考にします。
↓のMultitype Chart
https://react-chartjs-2.js.org/examples/multitype-chart

↓コードの全文はcodesandboxにあります
https://codesandbox.io/s/react-chartjs-2-mutitype-chart-ztqhx8?file=/package.json

コード解説

import

基本は1軸の棒グラフと同じですがimportするのはBarとかではなくChartになります。
import { Chart } from "react-chartjs-2";

import React, { useRef, useEffect } from "react";
import {
  Chart as ChartJS,
  LinearScale,
  CategoryScale,
  BarElement,
  PointElement,
  LineElement,
  Legend,
  Tooltip,
  LineController,
  BarController,
  Title
} from "chart.js";
import { Chart } from "react-chartjs-2";

ChartJS.register(
  LinearScale,
  CategoryScale,
  BarElement,
  PointElement,
  LineElement,
  Legend,
  Tooltip,
  LineController,
  BarController,
  Title
);

データとオプション

↓はcodesandboxに公開してるコードとはちょっと違います(ボタンの処理なくしてる)
returnしてるとこが棒グラフの時はBarでしたが今回は複合グラフなのでChartになってます。
<Chart type={"bar"} data={data} options={options} />

optionsのscalesでyとy1を設定していますがこれがy軸のIDになります。
datasetsでyAxisIDでこのIDを指定するとそれぞれの軸に割り振られます。

function getRandomInt(max) {
  return Math.floor(Math.random() * max);
}

const labels = ["January", "February", "March", "April", "May", "June", "July"];

const data = {
  labels,
  datasets: [
    {
      type: "line", // 折れ線
      label: "Dataset 1",
      borderColor: "rgb(255, 99, 132)",
      borderWidth: 2,
      fill: false,
      data: [1, 3, 4, 2, 3, 4, 2],
      yAxisID: "y1" // optionsで設定したIDを割り振ってY軸を設定する
    },
    {
      type: "bar", // 棒グラフ
      label: "Dataset 2",
      backgroundColor: "rgb(75, 192, 192)",
      borderColor: "white",
      borderWidth: 2,
      data: [11, 32, 43, 21, 32, 41, 21],
      yAxisID: "y" // Y軸の設定
    },
    {
      type: "bar", // 棒グラフ
      label: "Dataset 3",
      backgroundColor: "rgb(53, 162, 235)",
      data: [21, 33, 44, 32, 63, 34, 42],
      yAxisID: "y" // Y軸の設定
    }
  ]
};

export const options = {
  plugins: {
    title: {
      display: true,
      text: "Chart.js Bar Chart - multitype"
    },
    legend: { // 凡例の設定
      position: "bottom" // 下に配置
    }
  },
  responsive: true,
  scales: {
    x: {
      stacked: false
    },
    y: { // Y軸が複数あるのでyとy1のように軸にIDを付ける
      stacked: false,
      max: 100,
      min: 0
    },
    y1: {
      stacked: false,
      position: "right",
      max: 10,
      min: 0
    }
  }
};

export default function App() {
  return (
    <div className="App">
      <Chart type={"bar"} data={data} options={options} />
    </div>
  );
}

オプションとデータを動的に変更する

動的に変更する方法をreact-chartjs-2の公式が書いてた気がするんですけど見つからない…からchart.jsの説明してるページ載せときます↓これの.updateですね。
https://www.chartjs.org/docs/latest/developers/api.html

コード解説

早速コードを見ていきましょう。

↓コードの全文は2軸グラフでも載せたcodesandboxと同じです
https://codesandbox.io/s/react-chartjs-2-mutitype-chart-ztqhx8?file=/package.json

大事なのはuseRefを使ってref={chartRef}のようにchartの参照を取得します。
<Chart ref={chartRef} type={"bar"} data={data} options={options} />
あとはchartRef.current.でchartにアクセスしてデータやオプションの値を変更します。
値変更後はchartRef.current.update();で再レンダリングさせます。

function getRandomInt(max) {
  return Math.floor(Math.random() * max);
}

const labels = ["January", "February", "March", "April", "May", "June", "July"];

function getRandomInt(max) {
  return Math.floor(Math.random() * max);
}

const labels = ["January", "February", "March", "April", "May", "June", "July"];

const data = {
  labels,
  datasets: [ 
  // 省略
  ]
};

export const options = {
  // 省略
};

export default function App() {
  const chartRef = useRef(null); // chartの参照を取得するため必要

  useEffect(() => {
    randomData();
  }, []);

  const onClickButton = () => {
    randomData();
  };

  const randomData = () => {
    let data1 = [];
    let data2 = [];
    let data3 = [];
    for (let i = 0; i < labels.length; i++) {
      data1.push(getRandomInt(10));
      data2.push(getRandomInt(100));
      data3.push(getRandomInt(100));
    }

    // ref.currentでchartの参照にアクセスできる
    chartRef.current.data.datasets[0].data = data1;
    chartRef.current.data.datasets[1].data = data2;
    chartRef.current.data.datasets[2].data = data3;

    chartRef.current.update(); // update()を呼ぶと再レンダリングする
  };

  const UpYAxis1Max = () => {
    const max = chartRef.current.options.scales.y.max;
    chartRef.current.options.scales.y.max = max + 10;
    chartRef.current.update();
  };

  const UpYAxis1Min = () => {
    const max = chartRef.current.options.scales.y.max;
    chartRef.current.options.scales.y.max = max - 10;
    chartRef.current.update();
  };

  return (
    <div className="App">
      <Chart ref={chartRef} type={"bar"} data={data} options={options} />
      <button onClick={onClickButton}>random data</button>
      <p></p>
      <button onClick={UpYAxis1Max}>y axis1 max↑</button>
      <button onClick={UpYAxis1Min}>y axis1 max↓</button>
    </div>
  );
}

以上です。結構簡単ですね(私はこれに気付かず無駄にuseState使ってオブジェクト作り直して無理やり再レンダリングさせてました…orz)

Discussion