Financial Dashboard Chart Notes
At first, I was figuring out how to separate the chart-type components from the card-type components. While reading the Chart.js documentation, things started to make more sense. The idea is to keep all chart-related settings—like bar and line colors—in the chart component itself. This helps keep things standardized (so charts that use the same component look consistent).
A card component, on the other hand, contains more than just the chart. It might also include things like a title, subtitle, or other elements. Keeping these responsibilities separate makes the structure simpler.
Chart.js
Chart.js is a canvas-based library. You define your chart configuration first, and then it renders the chart onto a canvas element.
Using Chart.js with React/Vite
You’ll need to install both chart.js
and react-chartjs-2
:
npm install chart.js react-chartjs-2
Chart component react-chartjs-2 supports tree-shaking. You only need to register the chart types and components you actually use, which helps with performance.
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;
Common settings
Useful configuration options include color, borderColor, backgroundColor, label, title, and legend.
Note: label and legend can be defined at both the chart level and the dataset level.
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',
}
]
};
Dynamic Data with useContext + SWR
Instead of letting each chart fetch its own data, I’m using SWR for data fetching and wrapping the app with a React context to share the data across components.
This way, the data is fetched just once and passed down through context, so each chart can use the same source without triggering multiple requests.
Creating a context and 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>
);
}
Wrapping the app
import { DataProvider } from './context/DataContext';
import MyDashboard from './components/MyDashboard';
function App() {
return (
<DataProvider>
<MyDashboard />
</DataProvider>
);
}
Using the shared data in a chart component
import { useContext } from 'react';
import { DataContext } from '../context/DataContext';
function MyChartCard() {
const { data, isLoading, error } = useContext(DataContext);
if (isLoading) return <div>Loading...</div>;
if (error) return <div>Something went wrong</div>;
const chartData = transformDataForChart(data);
return <Bar data={chartData} />;
}
This approach keeps things clean and scalable, especially when you have multiple charts using the same dataset. Plus, it makes it easier to add features like caching or refresh buttons later on.