Skip to main content

Charting Libraries for React Dashboards

Dashboards without charts are just tables. Charts convey trends, patterns, and outliers in seconds—data that would take minutes to extract from rows and columns. Recharts, built specifically for React in 2015, dominates the SaaS ecosystem, used by 68% of React dashboards in 2026 according to npm download trends.

In my experience, Recharts wins for three reasons: (1) it's composable React components, not a wrapper around D3, (2) animations and responsive sizing are built-in, and (3) the learning curve is gentle. This article teaches you to build three chart types and connect them to live data.

What You'll Learn

You'll create:

  • A responsive line chart showing revenue over time
  • A bar chart comparing metrics across time periods
  • A pie chart of customer distribution by plan
  • Real-time chart updates when data changes
  • Tooltips and legends that explain the data

Prerequisites

You need the data-fetching setup from the previous article. Install Recharts:

npm install recharts

Understanding of SVG coordinates and color palettes is helpful but not required.

Step 1: Build a Revenue Line Chart

A line chart is perfect for time-series data: revenue over months, user growth, API calls per day. Create src/components/RevenueChart.tsx:

import {
LineChart,
Line,
XAxis,
YAxis,
CartesianGrid,
Tooltip,
Legend,
ResponsiveContainer,
} from 'recharts';
import { useQuery } from '@tanstack/react-query';

interface RevenueData {
month: string;
revenue: number;
target: number;
}

export function RevenueChart() {
const { data, isLoading } = useQuery<RevenueData[]>({
queryKey: ['revenue'],
queryFn: async () => {
const response = await fetch('/api/revenue');
if (!response.ok) throw new Error('Failed to fetch revenue');
return response.json();
},
});

if (isLoading) return <p>Loading chart...</p>;
if (!data) return <p>No data available</p>;

return (
<div className="bg-white rounded-lg shadow p-6">
<h2 className="text-lg font-semibold mb-4">Revenue Trend</h2>
<ResponsiveContainer width="100%" height={300}>
<LineChart data={data}>
<CartesianGrid strokeDasharray="3 3" />
<XAxis dataKey="month" />
<YAxis />
<Tooltip formatter={(value) => `$${value.toLocaleString()}`} />
<Legend />
<Line
type="monotone"
dataKey="revenue"
stroke="#3b82f6"
strokeWidth={2}
dot={{ fill: '#3b82f6', r: 5 }}
activeDot={{ r: 7 }}
name="Actual Revenue"
/>
<Line
type="monotone"
dataKey="target"
stroke="#9ca3af"
strokeWidth={2}
strokeDasharray="5 5"
name="Target"
/>
</LineChart>
</ResponsiveContainer>
</div>
);
}

Key components:

  • ResponsiveContainer makes the chart adapt to its parent width.
  • LineChart wraps all other elements.
  • Line defines a data series; you can add multiple lines.
  • Tooltip shows values on hover.
  • formatter in Tooltip customizes how values display (e.g., currency).

Step 2: Build a Bar Chart for Comparisons

Bar charts are ideal for comparing values across categories. Create src/components/ConversionChart.tsx:

import {
BarChart,
Bar,
XAxis,
YAxis,
CartesianGrid,
Tooltip,
Legend,
ResponsiveContainer,
} from 'recharts';
import { useQuery } from '@tanstack/react-query';

interface ConversionData {
name: string;
free: number;
pro: number;
enterprise: number;
}

export function ConversionChart() {
const { data, isLoading } = useQuery<ConversionData[]>({
queryKey: ['conversions'],
queryFn: async () => {
const response = await fetch('/api/conversions');
if (!response.ok) throw new Error('Failed to fetch conversions');
return response.json();
},
});

if (isLoading) return <p>Loading chart...</p>;
if (!data) return <p>No data available</p>;

return (
<div className="bg-white rounded-lg shadow p-6">
<h2 className="text-lg font-semibold mb-4">Conversions by Plan</h2>
<ResponsiveContainer width="100%" height={300}>
<BarChart data={data}>
<CartesianGrid strokeDasharray="3 3" />
<XAxis dataKey="name" />
<YAxis />
<Tooltip />
<Legend />
<Bar dataKey="free" fill="#ef4444" name="Free Plan" />
<Bar dataKey="pro" fill="#3b82f6" name="Pro Plan" />
<Bar dataKey="enterprise" fill="#10b981" name="Enterprise" />
</BarChart>
</ResponsiveContainer>
</div>
);
}

Each Bar is a separate series. Colors distinguish plans. Grouped bars (the default) make comparison easy.

Step 3: Build a Pie Chart for Distribution

Pie charts show parts of a whole. Create src/components/CustomerDistributionChart.tsx:

import {
PieChart,
Pie,
Cell,
Legend,
Tooltip,
ResponsiveContainer,
} from 'recharts';
import { useQuery } from '@tanstack/react-query';

interface PlanData {
name: string;
value: number;
}

const COLORS = ['#ef4444', '#3b82f6', '#10b981', '#f59e0b'];

export function CustomerDistributionChart() {
const { data, isLoading } = useQuery<PlanData[]>({
queryKey: ['customers-by-plan'],
queryFn: async () => {
const response = await fetch('/api/customers-by-plan');
if (!response.ok) throw new Error('Failed to fetch customer distribution');
return response.json();
},
});

if (isLoading) return <p>Loading chart...</p>;
if (!data) return <p>No data available</p>;

return (
<div className="bg-white rounded-lg shadow p-6">
<h2 className="text-lg font-semibold mb-4">Customers by Plan</h2>
<ResponsiveContainer width="100%" height={300}>
<PieChart>
<Pie
data={data}
cx="50%"
cy="50%"
labelLine={false}
label={({ name, percent }) => `${name} ${(percent * 100).toFixed(0)}%`}
outerRadius={80}
fill="#8884d8"
dataKey="value"
>
{data.map((entry, index) => (
<Cell key={`cell-${index}`} fill={COLORS[index % COLORS.length]} />
))}
</Pie>
<Tooltip formatter={(value) => `${value} customers`} />
<Legend />
</PieChart>
</ResponsiveContainer>
</div>
);
}

The label prop shows percentages on slices. Cell applies colors cyclically. A pie chart works best when you have 3–5 categories.

Step 4: Combine Charts in a Dashboard

Create src/pages/AnalyticsDashboard.tsx:

import { RevenueChart } from '../components/RevenueChart';
import { ConversionChart } from '../components/ConversionChart';
import { CustomerDistributionChart } from '../components/CustomerDistributionChart';

export default function AnalyticsDashboard() {
return (
<div className="space-y-6 p-6">
<h1 className="text-3xl font-bold text-gray-900">Analytics</h1>

<div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
<RevenueChart />
<ConversionChart />
</div>

<div className="grid grid-cols-1 lg:grid-cols-2 gap-6">
<CustomerDistributionChart />
<div className="bg-white rounded-lg shadow p-6">
<h2 className="text-lg font-semibold mb-4">Key Metrics</h2>
<ul className="space-y-2 text-gray-700">
<li>Total Revenue: <span className="font-bold">$142,450</span></li>
<li>Avg. Monthly Growth: <span className="font-bold">12%</span></li>
<li>Customer Lifetime Value: <span className="font-bold">$3,240</span></li>
<li>Churn Rate: <span className="font-bold">0.89%</span></li>
</ul>
</div>
</div>
</div>
);
}

This layout stacks charts responsively. On desktop, two charts per row; on mobile, one per row (via grid-cols-1 lg:grid-cols-2).

Charting Library Comparison

LibraryLearning CurveBundle SizeCustomizationBest For
RechartsLow35 KBHigh (React props)Most React dashboards
Chart.jsMedium50 KBMedium (config objects)Simple charts, canvas-based
PlotlyMedium120 KBHighInteractive scientific charts
D3Steep100 KBExtremeCustom bespoke visualizations

Recharts dominates React dashboards because its API is React-native: components and props instead of imperative method calls.

Key Takeaways

  • Recharts is a React-first charting library, not a wrapper around D3 or Canvas, so it feels natural to React developers.
  • ResponsiveContainer handles sizing—charts scale to their parent width automatically.
  • Tooltips and legends aid understanding without cluttering the chart itself.
  • Color consistency across charts (e.g., same color for "Pro" plan everywhere) improves dashboard coherence.
  • Pie charts work for 3–5 categories; use bar charts for comparisons across many categories.

Frequently Asked Questions

How do I update charts in real-time?

Charts re-render when their data prop changes. If you're using TanStack Query with refetchInterval, the chart updates automatically when new data arrives. For WebSocket updates, set state on message arrival and charts re-render instantly.

Can I customize chart colors?

Yes. In Recharts, use the stroke prop for line color, fill prop for bar/pie color, or colors array for multiple series. Or use the Cell component to color individual segments (as in the pie chart example).

Why is my chart not rendering?

Check (1) that data is not null/undefined, (2) that ResponsiveContainer has a parent with a defined height, and (3) that the chart type matches your data (e.g., don't use PieChart for time-series data).

How do I export a chart as an image?

Recharts renders to SVG (not Canvas), so right-click "Save image as..." works. For programmatic export, use a library like html2canvas or recharts-to-png to convert the SVG to PNG.

Should I use stacked bars or grouped bars?

Grouped bars are easier to compare across series. Stacked bars show totals and parts. Use stacked for "breakdown" questions (Where does revenue come from?); grouped for "comparison" questions (Which plan converts most?).

Further Reading