downloads-graph
Version:
A reusable React component to visualize npm download stats using Chart.js.
90 lines (80 loc) • 2.08 kB
JSX
// components/DownloadsChart.js
import './DownloadsGraph.css';
import { useEffect, useState } from "react";
import { Line } from "react-chartjs-2";
import {
Chart as ChartJS,
CategoryScale,
LinearScale,
PointElement,
LineElement,
Title,
Tooltip,
Legend,
} from "chart.js";
ChartJS.register(
CategoryScale,
LinearScale,
PointElement,
LineElement,
Title,
Tooltip,
Legend
);
export default function DownloadsGraph({
packageName,
borderColor,
backgroundColor,
}) {
const [chartData, setChartData] = useState(null);
useEffect(() => {
async function fetchDownloads() {
try {
const res = await fetch(
`https://api.npmjs.org/downloads/range/last-month/${packageName}`
);
const data = await res.json();
const labels = data.downloads.map((item) => item.day);
const downloads = data.downloads.map((item) => item.downloads);
setChartData({
labels,
datasets: [
{
label: `Downloads per day for ${packageName}`,
data: downloads,
borderColor: `${borderColor}`,
backgroundColor: `${backgroundColor}`,
fill: true,
tension: 0.3,
},
],
});
} catch (error) {
console.error("Failed to fetch downloads:", error);
}
}
fetchDownloads();
}, [packageName, borderColor, backgroundColor]);
if (!chartData) return <p>Loading chart...</p>;
const options = {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: { position: "top" },
title: { display: true, text: "NPM Downloads (Last 30 Days)" },
},
scales: {
x: {
ticks: { maxTicksLimit: 10 },
},
y: {
beginAtZero: true,
},
},
};
return (
<div className="downloads-chart-container" style={{ minHeight: "300px" }}>
<Line data={chartData} options={options} />
</div>
);
}