[React] rechars 사용해 차트 출력해보기

김나나·2024년 9월 16일

React

목록 보기
27/29
post-thumbnail

차트식 그래프를 출력해봐야하는 일이 있어서 찾아보던 중,
개인 커스터마이징도 잘 되고 사용법도 어렵지 않은 라이브러리라고 생각하여 rechars를 사용해보게 되었다.


✨Rechart 설치 및 사용법

  1. 터미널을 열어 npm install recharts 입력하여 설치

  2. 차트를 출력해줄 컴포넌트로, DietChart.js생성

  3. 공식 문서를 보면 샘플도 왕왕 찾아볼 수 있으니, 봐가면서 만들어보자.

+) 해당 글 참고

  1. 사용할 속성들부터 import해주기

  2. <LineChart />컴포넌트는 차트의 레이아웃, data를 주입하는 컴포넌트로, width와 height로 차트 영역을 지정, data로 데이터를 주입할 수 있다.

  3. 아래는 DietChart.js의 코드

import { useEffect, useState } from "react";
import axios from "axios";
import {
  BarChart,
  Bar,
  XAxis,
  YAxis,
  CartesianGrid,
  Tooltip,
  Legend,
  ResponsiveContainer,
} from "recharts";

export const DietChart = () => {
  const [chartData, setChartData] = useState([]);

  // 음식별 먹은 횟수를 받아오는 함수
  const fetchDietStats = async () => {
    try {
      const res = await axios.get("http://localhost:8800/diet-stats");
      setChartData(res.data);
    } catch (err) {
      console.log(err);
    }
  };

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

  return (
    <div>
      <h2>음식별 많이 먹은 횟수</h2>
      <ResponsiveContainer width="100%" height={400}>
        <BarChart data={chartData}>
          <CartesianGrid strokeDasharray="3 3" />
          <XAxis dataKey="food_name" />
          <YAxis />
          <Tooltip />
          <Legend />
          <Bar dataKey="count" fill="#8884d8" />
        </BarChart>
      </ResponsiveContainer>
    </div>
  );
};
  1. 아래는 이름별로 먹은 횟수를 계산하는 API를 server.js에 작성
app.get("/diet-stats", (req, res) => {
  const q =
    "SELECT food_name, COUNT(*) as count FROM diettb GROUP BY food_name";
  db.query(q, (err, data) => {
    if (err) return res.status(500).json(err);
    return res.json(data);
  });
});

  1. 해당 차트 컴포넌트를 필요한 부분(Feedback.js에 넣어줌)에 아래처럼 넣어주면 된다.


아래는 list에서 선택한 음식 코드에 해당하는 음식을 날짜별로 먹은 횟수를 그래프로 나타낸 코드!

server.js에 API 작성

// food_code_no에 맞는 음식을 날짜별로 먹은 횟수를 가져오는 API
app.get("/food-stats/:diet_no", (req, res) => {
  const dietNo = req.params.diet_no;

  // 먼저 diet_no에 맞는 food_code_no를 가져오는 쿼리
  const getFoodCodeQuery = "SELECT food_code_no FROM diettb WHERE diet_no = ?";

  db.query(getFoodCodeQuery, [dietNo], (err, data) => {
    if (err) return res.status(500).json(err);

    if (data.length === 0) return res.status(404).json("Data not found");

    const foodCodeNo = data[0].food_code_no;

    // food_code_no에 맞는 날짜별 음식 섭취 횟수를 계산하는 쿼리
    const q = `
      SELECT reg_date, COUNT(*) as count 
      FROM diettb 
      WHERE food_code_no = ?
      GROUP BY reg_date
      ORDER BY reg_date
    `;

    db.query(q, [foodCodeNo], (err, stats) => {
      if (err) return res.status(500).json(err);
      return res.json(stats);
    });
  });
});
  1. 구분을 위해 CheckDietChart.js파일을 생성해서 아래처럼 코드 작성
import { useEffect, useState } from "react";
import { useParams } from "react-router-dom";
import axios from "axios";
import {
  LineChart,
  Line,
  XAxis,
  YAxis,
  CartesianGrid,
  Tooltip,
  Legend,
  ResponsiveContainer,
} from "recharts";

export const CheckDietChart = () => {
  const { id } = useParams(); // URL에서 diet_no 파라미터 가져오기
  const [chartData, setChartData] = useState([]);
  const [loading, setLoading] = useState(true);

  const fetchFoodStats = async () => {
    try {
      // API 호출해서 diet_no에 따른 food_code_no를 사용한 음식 기록 조회
      const res = await axios.get(`http://localhost:8800/food-stats/${id}`);
      setChartData(res.data);
    } catch (err) {
      console.log(err);
    } finally {
      setLoading(false);
    }
  };

  useEffect(() => {
    fetchFoodStats();
  }, [id]);

  if (loading) return <div>Loading...</div>;

  return (
    <div>
      <h2>음식 날짜별 섭취 횟수</h2>
      <ResponsiveContainer width="100%" height={400}>
        <LineChart data={chartData}>
          <CartesianGrid strokeDasharray="3 3" />
          <XAxis dataKey="reg_date" />
          <YAxis />
          <Tooltip />
          <Legend />
          <Line type="monotone" dataKey="count" stroke="#8884d8" />
        </LineChart>
      </ResponsiveContainer>
    </div>
  );
};

profile
10분의 정리로 10시간을 아낄 수 있다는 마음으로 글을 작성하고 있습니다💕

0개의 댓글