Financial Dashboard圖表
一開始在想chart類型和card類型的component要怎麼區分,邊看chart.js文件邊慢慢有點頭緒,可以把chart本身的設定,像是bar、line顏色相關的options寫在chart component,這樣就能達到標準化的目的 (引用同個component的長相會一致)
card除了chart component之外還包含其他要素,像是title、subtitle、等,分開處理比較單純
Chart.js
Chart.js是一個基於Canvas的函式庫,在繪製圖形之前先做好需要的設定,再把canvas畫上頁面
在React/Vite使用Chart.js
Chart.js + react-chartjs-2,兩個函式庫都要安裝
npm install chart.js react-chartjs-2
Chart component
react-chartjs-2 有做tree-shaking,註冊會用到的圖形以節省效能
import React from 'react';
import { Bar } from 'react-chartjs-2';
import { Chart as ChartJS, CategoryScale, LinearScale, BarElement, Title, Tooltip, Legend } from 'chart.js';
// Register Chart.js components
ChartJS.register(
CategoryScale,
LinearScale,
BarElement,
Title,
Tooltip,
Legend
);
function MyBarChart() {
const 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
}]
};
return <Bar data={data} />;
}
export default MyBarChart;
常用設定
color, borderColor, backgroundColor, label, title, legend label和legend有分為chart層級和graph層級
const data = {
labels: ['A', 'B', 'C'],
datasets: [
{
label: 'Dataset 1',
data: [1, 2, 3],
borderColor: '#36A2EB',
backgroundColor: '#9BD0F5',
},
{
label: 'Dataset 2',
data: [2, 3, 4],
borderColor: '#FF6384',
backgroundColor: '#FFB1C1',
}
]
};
動態資料呈現:useContext + SWR
如果每個圖表都各自去打 API,會很難統一資料的來源與更新頻率。可以用 SWR 來處理資料請求,再用 React context 把資料傳下去,讓不同的圖表共用同一份資料。
context 的好處是資料載入一次就好,每個元件可以直接取用,不用重複發出request。
建立 context 和 provider
// context/DataContext.js
import React, { createContext } from 'react';
import useSWR from 'swr';
export const DataContext = createContext();
const fetcher = (url) => fetch(url).then((res) => res.json());
export function DataProvider({ children }) {
const { data, error, isLoading } = useSWR('/api/stock', fetcher);
return (
<DataContext.Provider value={{ data, error, isLoading }}>
{children}
</DataContext.Provider>
);
}
在 App 加上 provider
import { DataProvider } from './context/DataContext';
import MyDashboard from './components/MyDashboard';
function App() {
return (
<DataProvider>
<MyDashboard />
</DataProvider>
);
}
子元件中使用資料
import { useContext } from 'react';
import { DataContext } from '../context/DataContext';
function MyChartCard() {
const { data, isLoading, error } = useContext(DataContext);
if (isLoading) return <div>載入中...</div>;
if (error) return <div>資料錯誤</div>;
const chartData = transformDataForChart(data);
return <Bar data={chartData} />;
}
這樣做就能讓不同圖表元件共用一份 SWR 資料來源,也方便之後加上 refresh 或 cache 邏輯。