概要
- Reactアプリケーションで、データ可視化や分析ダッシュボードを作成する際に利用される
Recharts
ライブラリを紹介 -
LineChart
やBarChart
などのコンポーネントを用いて、シンプルかつ拡張可能なチャート描画を実現 - プロジェクトの規模や目的に応じて、ディレクトリ構成や 責務分離(FE/BE/DB) をどう設計するかが重要
Recharts
を導入することで 「データを視覚的に理解しやすい形で提示する」 Reactアプリを効率的に作成できる
実施条件
- React + TypeScript プロジェクトが構築済みであること
- APIとの通信(
axios
など)に関する基礎知識があること - データの保存方法(DB利用 or 直接API呼び出し)を理解していること
- Prisma + DB(PostgreSQLやMySQLなど)がセットアップされていること
環境
ツール | バージョン | 目的 |
---|---|---|
Node.js | 22.5.1 | Reactアプリ実行環境 |
React | 19.1.0 | UI構築 |
TypeScript | 4.9 | 型定義による安全な開発 |
Recharts | 2.15.4 | データ可視化ライブラリ |
Prisma | 5.x | DB ORM |
ディレクトリ構成
Prismaを使う場合も基本的な構成は同じ。ただし、DBスキーマは prisma/schema.prisma
に定義する。
Prisma
project-root/
├── frontend/
│ ├── src/
│ │ ├── components/
│ │ │ └── CryptoChart.tsx
│ │ ├── services/
│ │ │ └── api.ts
│ │ └── pages/
│ │ └── Dashboard.tsx
├── backend/
│ ├── routes/
│ │ └── cryptoRoutes.js
│ ├── controllers/
│ │ └── cryptoController.js
│ ├── services/
│ │ └── coingeckoService.js
│ └── prisma/
│ └── schema.prisma
データフロー
パターン①:保存型(FE + BE + DB)
データの流れ(クライアント入力データ)
データの流れ(外部APIデータ)
コード
frontend/
services/api.ts
バックエンドAPIにリクエストしてデータを取得する。
services/api.ts
import axios from 'axios';
export const fetchCryptoPrices = async () => {
const res = await axios.get('/api/crypto/prices'); // BEのエンドポイント
return res.data; // { timestamp, coin, price }
};
components/CryptoChart.tsx
Rechartsを使ったラインチャート描画。
components/CryptoChart.tsx
import { LineChart, Line, XAxis, YAxis, Tooltip } from 'recharts';
export default function CryptoChart({
data,
}: {
data: { timestamp: string; price: number }[];
}) {
return (
<LineChart width={600} height={300} data={data}>
<XAxis dataKey="timestamp" />
<YAxis />
<Tooltip />
<Line type="monotone" dataKey="price" stroke="#82ca9d" />
</LineChart>
);
}
pages/Dashboard.tsx
バックエンドからデータを取得してチャートに渡す。
pages/Dashboard.tsx
import { useEffect, useState } from 'react';
import { fetchCryptoPrices } from '../services/api';
import CryptoChart from '../components/CryptoChart';
export default function Dashboard() {
const [data, setData] = useState<{ timestamp: string; price: number }[]>([]);
useEffect(() => {
const fetchData = async () => {
try {
const res = await fetchCryptoPrices();
setData([{ timestamp: res.timestamp, price: res.price }]);
} catch (error) {
console.error('Failed to fetch crypto prices:', error);
}
};
fetchData();
}, []);
return (
<div style={{ padding: '1rem' }}>
<h2>Crypto Price Dashboard</h2>
<CryptoChart data={data} />
</div>
);
}
backend/
routes/cryptoRoutes.js
エンドポイント定義。
routes/cryptoRoutes.js
import express from 'express';
import { getLatestPrice } from '../controllers/cryptoController.js';
const router = express.Router();
router.get('/prices', getLatestPrice);
export default router;
controllers/cryptoController.js
APIコールとDB保存を行い、フロントに返すロジック。
controllers/cryptoController.js
import { PrismaClient } from '@prisma/client';
import { fetchPriceFromAPI } from '../services/coingeckoService.js';
const prisma = new PrismaClient();
// 外部APIのデータをDBに保存して返す
export const getLatestPrice = async (req, res) => {
try {
const coin = req.query.coin || 'bitcoin';
const currency = req.query.currency || 'usd';
// 1. 外部APIから最新価格を取得
const apiData = await fetchPriceFromAPI(coin, currency);
const price = apiData[coin][currency];
// 2. DBに保存
const record = await prisma.cryptoPrice.create({
data: {
timestamp: new Date(),
coin,
price,
},
});
// 3. フロントに返却
res.json({
timestamp: record.timestamp,
coin: record.coin,
price: record.price,
});
} catch (error) {
console.error(error);
res.status(500).json({ error: 'Failed to fetch price' });
}
};
services/coingeckoService.js
外部APIから仮想通貨価格を取得するロジック。
services/coingeckoService.js
import axios from 'axios';
export const fetchPriceFromAPI = async (coin = 'bitcoin', currency = 'usd') => {
const res = await axios.get(
`https://api.coingecko.com/api/v3/simple/price?ids=${coin}&vs_currencies=${currency}`
);
return res.data;
};
prisma/schema.prisma
DBモデル(例:SequelizeやPrismaで定義)。
prisma/schema.prisma
// Prismaの例
datasource db {
provider = "mysql" // PosgresSQLやSQLiteでも可
url = env("DATABASE_URL")
}
generator client {
provider = "prisma-client-js"
}
model CryptoPrice {
id Int @id @default(autoincrement())
timestamp DateTime @default(now())
coin String
price Float
}
ディレクトリ設計まとめ
パターン | 特徴 | 適用例 |
---|---|---|
保存型 | 履歴分析・安定性あり | ダッシュボード、統計分析 |
リアルタイム型 | 即時性・軽量 | トレンド表示、速報性重視アプリ |
直接呼び出し型 | 最速・最小構成 | プロトタイプ、個人利用ツール |