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?

[React][Recharts][Prisma] `Recharts` の使い方 (パターン① : 保存型 (FE + BE + DB))

Last updated at Posted at 2025-08-25

概要

  • Reactアプリケーションで、データ可視化分析ダッシュボードを作成する際に利用される Recharts ライブラリを紹介
  • LineChartBarChart などのコンポーネントを用いて、シンプルかつ拡張可能なチャート描画を実現
  • プロジェクトの規模や目的に応じて、ディレクトリ構成責務分離(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
}

ディレクトリ設計まとめ

パターン 特徴 適用例
保存型 履歴分析・安定性あり ダッシュボード、統計分析
リアルタイム型 即時性・軽量 トレンド表示、速報性重視アプリ
直接呼び出し型 最速・最小構成 プロトタイプ、個人利用ツール

参考リンク

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?