Closed31

RechartsをReact / Next(TypeScript)で利用する

ryopenguinryopenguin

ブログ記事の内容を分析し、それを可視化するダッシュボードを作りたいと考えた。
詳しくはこの記事を参照されたい。
このスクラップでは、D3.jsのReactラッパーであるRechartsについて学んでいく。

まずは「Rechartsで任意のグラフをNextのページとして表示するところ」までをゴールとする。

ryopenguinryopenguin

今日はとりあえず、Reactのサンプルアプリ上にRechartsで何かグラフを出してみるところまでやってみる。

その後Nextで作っている自分のブログにダッシュボードのサンプルを出してみる。

ryopenguinryopenguin

空コンポーネント chart.tsx を作った。これで色々実験する

const Chart = () => {};

export default Chart;
ryopenguinryopenguin

Getting Startedを見る。
Propsにデータを渡すと描画してくれるらしい。

PlainなJSで書かれているのでTypeScriptで書いてみるか。

import { LineChart, Line } from 'recharts';
const data = [{name: 'Page A', uv: 400, pv: 2400, amt: 2400}, ...];

const renderLineChart = (
  <LineChart width={400} height={400} data={data}>
    <Line type="monotone" dataKey="uv" stroke="#8884d8" />
  </LineChart>
);
ryopenguinryopenguin

typesインストールするの忘れてた。

yarn add --dev @types/recharts

ryopenguinryopenguin

Componentにデータベタ書きで普通に描画できたわ。
あとでデータなどをPropsにしてみよう

ryopenguinryopenguin

なるほど、ベースとなる~~Chartというコンポーネントの子要素としてX軸やY軸のコンポーネントがあって、これらをカスタマイズしていく感じなのね。

ryopenguinryopenguin

とりあえずチュートリアルをさらったので LineChart.tsx コンポーネントを作って、上位のコンポーネントからデータを受け取れるようにしよう

ryopenguinryopenguin

LineChart.tsx だとRechartsの命名とバッティングするので、ウェブサイトのデータを描画するものとして TrafficChart.tsxとした。

ryopenguinryopenguin

今の事象

components配下にTrafficChart.tsxを作り、感じでpropsを受け取るようにした

const TrafficChart = (chartSettings: chartSettings) => {
  return (
    <LineChart width={600} height={300} data={chartSettings.dataCollection}>
      <Line type="monotone" dataKey={chartSettings.target} stroke="#8884d8" />
      <CartesianGrid stroke="#ccc" strokeDasharray="5 5" />
      <XAxis dataKey={chartSettings.xaxis} />
      <YAxis />
      <Tooltip />
    </LineChart>
  );
};

chartSettings typeはtypeフォルダから読み込む

export type dailyPageTraffic = {
  pageName: string;
  uu: number;
  pv: number;
  date: string;
};

export type chartSettings = {
  dataCollection: dailyPageTraffic[];
  target: string;
  xaxis: string;
};

表示用のコンポーネント chart.tsxからこんな感じで呼び出そうとするとエラー

import { chartSettings } from "../types/TrafficChartType";
import TrafficChart from "./TrafficChart";

const testData: chartSettings = {
  dataCollection: [
    {
      pageName: "Page A",
      uu: 110,
      pv: 120,
      date: "2022-12-02",
    },
  ],
  target: "uu",
  xaxis: "date",
};

const Chart = () => {
  return (
    <>
      <TrafficChart chartSetting={testData} />
    </>
  );
};

export default Chart;

ryopenguinryopenguin

エラーの内容

ERROR in src/components/chart.tsx:20:21
TS2322: Type '{ chartSetting: chartSettings; }' is not assignable to type 'IntrinsicAttributes & chartSettings'.
  Property 'chartSetting' does not exist on type 'IntrinsicAttributes & chartSettings'.
    18 |   return (
    19 |     <>
  > 20 |       <TrafficChart chartSetting={testData} />
       |                     ^^^^^^^^^^^^
    21 |     </>
    22 |   );
    23 | };
ryopenguinryopenguin

調べた感じ、子要素の型定義に問題がありそうだがいまいちわからない。
IntrinsicAttributes ってなんなんやろか

ryopenguinryopenguin

一旦よくわからないので今日は TrafficChart.tsxで描画できればいいことにするか。描画コンポーネントがデータを持ってしまうのはいいのかなあ。

例えば今後Nextの/pages 配下のページで getServerSideProps をしたあと、PropsをグラフコンポーネントにPropsに渡したいんだよな。今だとPagesにベタ書きになってしまう

ryopenguinryopenguin

childrenとかpropsを雰囲気で書いているので明日以降その辺勉強してみよう

ryopenguinryopenguin

チュートリアルのこれを参考に子コンポーネントを書き換える

function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}
ryopenguinryopenguin

親コンポーネントではnameで呼ぶけど、子コンポーネントではprops.nameで受け取らなければいけない。

function Welcome(props) {
  return <h1>Hello, {props.name}</h1>;
}

function App() {
  return (
    <div>
      <Welcome name="Sara" />
      <Welcome name="Cahal" />
      <Welcome name="Edite" />
    </div>
  );
}
ryopenguinryopenguin

よーしグラフコンポーネントにpropsでデータ送れるようになった〜
これでpageからグラフコンポーネントにデータ送るとかできる〜〜〜

/src/App.txs

import React from "react";
import "./App.css";
import TrafficChart from "./components/TrafficChart";

const sample = [
  { pageName: "Page A", uu: 1200, pv: 1300, date: "2022-12-09" },
  {
    pageName: "Page B",
    uu: 1220,
    pv: 1350,
    date: "12/10",
  },
  {
    pageName: "Page C",
    uu: 1290,
    pv: 1500,
    date: "12/11",
  },
  {
    pageName: "Page D",
    uu: 1300,
    pv: 1400,
    date: "12/12",
  },
  {
    pageName: "Page E",
    uu: 1500,
    pv: 1430,
    date: "12/13",
  },
];
const target = "uu";
const xaxis = "date";

function App() {
  return (
    <>
      <TrafficChart dataCollection={sample} target={target} xaxis={xaxis} />
    </>
  );
}

export default App;

/src/components/TrafficChart.tsx

import {
  LineChart,
  Line,
  CartesianGrid,
  XAxis,
  YAxis,
  Tooltip,
} from "recharts";

type trafficData = {
  pageName: string;
  uu: number;
  pv: number;
  date: string;
};

type props = {
  dataCollection: trafficData[];
  target: string;
  xaxis: string;
};

const TrafficChart = (props: props) => {
  return (
    <LineChart width={600} height={300} data={props.dataCollection}>
      <Line type="monotone" dataKey={props.target} stroke="#8884d8" />
      <CartesianGrid stroke="#ccc" strokeDasharray="5 5" />
      <XAxis dataKey={props.xaxis} />
      <YAxis />
      <Tooltip />
    </LineChart>
  );
};

export default TrafficChart;

ryopenguinryopenguin

データ分析系のライブラリとTypeScriptって相性良かったりする?
PythonとかR書いてても型欲しい時あるもんな〜

このスクラップは2022/12/19にクローズされました