Use React Hooks and Chart.js without react-chartjs-2

kimizuy

はじめに

こんにちは。kimizuy です。

今回は Chart.js を React Hooks(とついでに TypeScript)を使ってレンダリングする方法をご紹介します。

これまでの経験上、JavaScript でチャートライブラリを使う際、 Chart.js はかなり最初のほうで検討候補に上がることが多いです。

それと React を組み合わせる場合は、検索上位であることやサンプル数の多さから基本的に react-chartjs-2 というラッパーライブラリを使うことを考えます。

ただ、react-chartjs-2 は最近(2021/8/31 時点で)レポジトリ上の動きがあまりないようで、イシューへの対応も鈍い印象があります。

そこで本記事では react-chartjs-2 に依存せず、シンプルに React Hooks のみで Chart.js を利用していきます。

tldr

早速、コード例をご紹介します。

CodeSandbox も用意しました。実際に触って挙動を確かめてみてください。

import {
  Chart,
  ChartConfiguration,
  BarElement,
  LinearScale,
  BarController,
  CategoryScale,
  Tooltip
} from "chart.js";
import { useEffect, useRef } from "react";
import "./styles.css";

const config: ChartConfiguration = {
  type: "bar",
  data: {
    labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
    datasets: [
      {
        label: "# of Votes",
        data: [12, 19, 3, 5, 2, 3],
        backgroundColor: [
          "rgba(255, 99, 132, 0.2)",
          "rgba(54, 162, 235, 0.2)",
          "rgba(255, 206, 86, 0.2)",
          "rgba(75, 192, 192, 0.2)",
          "rgba(153, 102, 255, 0.2)",
          "rgba(255, 159, 64, 0.2)"
        ],
        borderColor: [
          "rgba(255, 99, 132, 1)",
          "rgba(54, 162, 235, 1)",
          "rgba(255, 206, 86, 1)",
          "rgba(75, 192, 192, 1)",
          "rgba(153, 102, 255, 1)",
          "rgba(255, 159, 64, 1)"
        ],
        borderWidth: 1
      }
    ]
  },
  options: {
    scales: {
      y: {
        beginAtZero: true
      }
    }
  }
};

const Bar = () => {
  const canvasRef = useRef<HTMLCanvasElement>(null);
  useEffect(() => {
    const element = canvasRef.current;
    if (!element) return;
    // https://www.chartjs.org/docs/next/getting-started/integration.html#bundlers-webpack-rollup-etc
    Chart.register(
      BarElement,
      BarController,
      LinearScale,
      CategoryScale,
      Tooltip
    );
    const chart = new Chart(element, config);
    return () => chart.destroy();
  });

  return <canvas ref={canvasRef} />;
};

export default function App() {
  return (
    <div className="App">
      <Bar />
    </div>
  );
}

簡単な解説

Chart.js は v3 からツリーシェイキングに対応しています。Chart.resister() で利用するモジュールを登録します。今回の場合はバーチャートに必要なモジュールを登録しました。

const chart = new Chart(element, config) で初期化しています。

return () => chart.destroy()クリーンアップ関数です。次のレンダリングの最初に古いインスタンスを消去することでメモリリークの発生を防ぎます。

おわりに

react-chartjs-2 で地雷を踏んで時間を溶かしてしまい筆をとりました。

紹介した手法でこれからハマらない保証もないですが、依存するライブラリが減らせると原因を究明するのも早くなりそうです。

以上、本記事が誰かのお役に立てれば幸いです。

Gaji-Laboでは、React経験が豊富なフロントエンドエンジニアを募集しています

弊社ではReactの知見で事業作りに貢献したいフロントエンドエンジニアを募集しています。大きな制作会社や事業会社とはひと味もふた味も違うGaji-Laboを味わいに来ませんか?

もちろん、一緒にお仕事をしてくださるパートナーさんも随時募集中です。まずはお気軽に声をかけてください。お仕事お問い合わせや採用への応募、共に大歓迎です!

求人応募してみる!

kimizuy

投稿者 Yamasaki Kimizu

React, Redux, TypeScript プロジェクトでフロントエンド領域を担当。個人でも Next.js アプリの開発をしています。日課はRSSで取得した技術記事を読むこと、最近の関心は Core Web Vitals です。将来はでかい犬が飼いたいです。