Recharts Chart Examples in React

Recharts examples I actually reuse: line, bar, pie, radar, treemap, sunburst, and the tooltip/legend bits that go with them.

Recharts React Examples
← All posts
Recharts Chart Examples in React

Why Recharts

Recharts is the chart library I reach for in React. There's no giant options object. You nest components the same way you nest divs: a LineChart wraps the plot, Line is a series, Tooltip is just another child. If you've written React at all, that mental model clicks pretty fast.

Each example below is a small component with its own data, so you can paste it into a file and run it. There's a preview next to the code. For a broader look at the library, see our Recharts page or the official docs.

Install

npm install recharts

LineChart

If you only pick up one Recharts chart, start here. It's what I use for anything that moves over time — traffic, revenue, signups. Drop in a second Line and it shares the axes automatically, so comparing two series is just another component.

Preview

Code

import {
  LineChart,
  Line,
  XAxis,
  YAxis,
  CartesianGrid,
  Tooltip,
  Legend,
  ResponsiveContainer,
} from "recharts";

const data = [
  { name: "Jan", uv: 4000, pv: 2400 },
  { name: "Feb", uv: 3000, pv: 1398 },
  { name: "Mar", uv: 2000, pv: 9800 },
  { name: "Apr", uv: 2780, pv: 3908 },
  { name: "May", uv: 1890, pv: 4800 },
  { name: "Jun", uv: 2390, pv: 3800 },
];

export function Example() {
  return (
    <ResponsiveContainer width="100%" height={280}>
      <LineChart data={data}>
        <CartesianGrid strokeDasharray="3 3" />
        <XAxis dataKey="name" />
        <YAxis />
        <Tooltip />
        <Legend />
        <Line type="monotone" dataKey="pv" stroke="#5b9fd4" />
        <Line type="monotone" dataKey="uv" stroke="#e8b84a" />
      </LineChart>
    </ResponsiveContainer>
  );
}

AreaChart

Same bones as a line chart, but filled in. The fill makes the volume obvious, which is why people use it for cumulative stuff. Give both Area components the same stackId if you want them stacked; skip stackId and they'll overlap instead.

Preview

Code

import {
  AreaChart,
  Area,
  XAxis,
  YAxis,
  CartesianGrid,
  Tooltip,
  Legend,
  ResponsiveContainer,
} from "recharts";

const data = [
  { name: "Jan", uv: 4000, pv: 2400 },
  { name: "Feb", uv: 3000, pv: 1398 },
  { name: "Mar", uv: 2000, pv: 9800 },
  { name: "Apr", uv: 2780, pv: 3908 },
  { name: "May", uv: 1890, pv: 4800 },
  { name: "Jun", uv: 2390, pv: 3800 },
];

export function Example() {
  return (
    <ResponsiveContainer width="100%" height={280}>
      <AreaChart data={data}>
        <CartesianGrid strokeDasharray="3 3" />
        <XAxis dataKey="name" />
        <YAxis />
        <Tooltip />
        <Legend />
        <Area
          type="monotone"
          dataKey="uv"
          stackId="1"
          stroke="#e8b84a"
          fill="#e8b84a"
        />
        <Area
          type="monotone"
          dataKey="pv"
          stackId="1"
          stroke="#5b9fd4"
          fill="#5b9fd4"
        />
      </AreaChart>
    </ResponsiveContainer>
  );
}

BarChart

Bars are the right call when the x-axis is categories, not a continuous line. Two Bar children with different dataKeys sit next to each other. Want them stacked? Same trick as AreaChart: one stackId on both.

Preview

Code

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

const data = [
  { name: "Jan", uv: 4000, pv: 2400 },
  { name: "Feb", uv: 3000, pv: 1398 },
  { name: "Mar", uv: 2000, pv: 9800 },
  { name: "Apr", uv: 2780, pv: 3908 },
  { name: "May", uv: 1890, pv: 4800 },
  { name: "Jun", uv: 2390, pv: 3800 },
];

export function Example() {
  return (
    <ResponsiveContainer width="100%" height={280}>
      <BarChart data={data}>
        <CartesianGrid strokeDasharray="3 3" />
        <XAxis dataKey="name" />
        <YAxis />
        <Tooltip />
        <Legend />
        <Bar dataKey="pv" fill="#5b9fd4" radius={[4, 4, 0, 0]} />
        <Bar dataKey="uv" fill="#e8b84a" radius={[4, 4, 0, 0]} />
      </BarChart>
    </ResponsiveContainer>
  );
}

ComposedChart

This is the "I need bars and a line on the same plot" chart. Mix an Area, a Bar, and a Line without wiring up two charts. I use it when one number is a volume and another is a trend sitting on top.

Preview

Code

import {
  ComposedChart,
  Area,
  Bar,
  Line,
  XAxis,
  YAxis,
  CartesianGrid,
  Tooltip,
  Legend,
  ResponsiveContainer,
} from "recharts";

const data = [
  { name: "Jan", uv: 4000, pv: 2400, amt: 2400 },
  { name: "Feb", uv: 3000, pv: 1398, amt: 2210 },
  { name: "Mar", uv: 2000, pv: 9800, amt: 2290 },
  { name: "Apr", uv: 2780, pv: 3908, amt: 2000 },
  { name: "May", uv: 1890, pv: 4800, amt: 2181 },
  { name: "Jun", uv: 2390, pv: 3800, amt: 2500 },
];

export function Example() {
  return (
    <ResponsiveContainer width="100%" height={280}>
      <ComposedChart data={data}>
        <CartesianGrid strokeDasharray="3 3" />
        <XAxis dataKey="name" />
        <YAxis />
        <Tooltip />
        <Legend />
        <Area type="monotone" dataKey="amt" fill="#4db6a0" stroke="#4db6a0" />
        <Bar dataKey="pv" barSize={18} fill="#5b9fd4" />
        <Line type="monotone" dataKey="uv" stroke="#e8b84a" />
      </ComposedChart>
    </ResponsiveContainer>
  );
}

ScatterChart

For actual x/y pairs, not months-as-labels. Each Scatter is a group, so two campaigns can live on one plot. One gotcha: set type="number" on both axes, or Recharts treats the values like category names and the dots end up in the wrong place.

Preview

Code

import {
  ScatterChart,
  Scatter,
  XAxis,
  YAxis,
  CartesianGrid,
  Tooltip,
  Legend,
  ResponsiveContainer,
} from "recharts";

const seriesA = [
  { x: 10, y: 30 },
  { x: 25, y: 48 },
  { x: 40, y: 35 },
  { x: 55, y: 70 },
  { x: 70, y: 52 },
  { x: 85, y: 90 },
];

const seriesB = [
  { x: 15, y: 20 },
  { x: 32, y: 38 },
  { x: 48, y: 55 },
  { x: 60, y: 42 },
  { x: 78, y: 68 },
  { x: 92, y: 80 },
];

export function Example() {
  return (
    <ResponsiveContainer width="100%" height={280}>
      <ScatterChart>
        <CartesianGrid />
        <XAxis type="number" dataKey="x" name="Spend" />
        <YAxis type="number" dataKey="y" name="Conversions" />
        <Tooltip cursor={{ strokeDasharray: "3 3" }} />
        <Legend />
        <Scatter name="Campaign A" data={seriesA} fill="#e8b84a" />
        <Scatter name="Campaign B" data={seriesB} fill="#5b9fd4" />
      </ScatterChart>
    </ResponsiveContainer>
  );
}

PieChart

Parts of a whole. I almost always set innerRadius so it becomes a donut — the hole makes the slices easier to read, and you can drop a total in the middle later. Cell is how you lock a color to each slice instead of taking the defaults.

Preview

Code

import {
  PieChart,
  Pie,
  Cell,
  Tooltip,
  Legend,
  ResponsiveContainer,
} from "recharts";

const data = [
  { name: "Product", value: 42 },
  { name: "Services", value: 33 },
  { name: "Other", value: 25 },
];

const COLORS = ["#e8b84a", "#5b9fd4", "#4db6a0"];

export function Example() {
  return (
    <ResponsiveContainer width="100%" height={280}>
      <PieChart>
        <Pie
          data={data}
          dataKey="value"
          nameKey="name"
          cx="50%"
          cy="50%"
          innerRadius={55}
          outerRadius={90}
          paddingAngle={2}
          label
        >
          {data.map((_, index) => (
            <Cell key={index} fill={COLORS[index]} />
          ))}
        </Pie>
        <Tooltip />
        <Legend />
      </PieChart>
    </ResponsiveContainer>
  );
}

RadarChart

The spider-web one. It's good when you're scoring a handful of attributes at once — speed vs quality vs docs, that kind of thing. PolarAngleAxis labels the spokes. Each Radar is one product, or one person.

Preview

Code

import {
  RadarChart,
  Radar,
  PolarGrid,
  PolarAngleAxis,
  PolarRadiusAxis,
  Tooltip,
  Legend,
  ResponsiveContainer,
} from "recharts";

const data = [
  { subject: "Speed", A: 120, B: 110, fullMark: 150 },
  { subject: "Quality", A: 98, B: 130, fullMark: 150 },
  { subject: "Support", A: 86, B: 130, fullMark: 150 },
  { subject: "Features", A: 99, B: 100, fullMark: 150 },
  { subject: "UX", A: 85, B: 90, fullMark: 150 },
  { subject: "Docs", A: 65, B: 85, fullMark: 150 },
];

export function Example() {
  return (
    <ResponsiveContainer width="100%" height={320}>
      <RadarChart data={data}>
        <PolarGrid />
        <PolarAngleAxis dataKey="subject" />
        <PolarRadiusAxis />
        <Radar
          name="Product A"
          dataKey="A"
          stroke="#e8b84a"
          fill="#e8b84a"
          fillOpacity={0.45}
        />
        <Radar
          name="Product B"
          dataKey="B"
          stroke="#5b9fd4"
          fill="#5b9fd4"
          fillOpacity={0.3}
        />
        <Tooltip />
        <Legend />
      </RadarChart>
    </ResponsiveContainer>
  );
}

RadialBarChart

Circular bars. A bit extra, but they work for a small set of percentages. Put a fill on each row of data and point RadialBar at the number. I park the legend on the right so the labels aren't sitting on the rings.

Preview

Code

import {
  RadialBarChart,
  RadialBar,
  Tooltip,
  Legend,
  ResponsiveContainer,
} from "recharts";

const data = [
  { name: "18–24", uv: 31.47, fill: "#e8b84a" },
  { name: "25–29", uv: 26.69, fill: "#c9922e" },
  { name: "30–34", uv: 15.69, fill: "#5b9fd4" },
  { name: "35–39", uv: 8.22, fill: "#4db6a0" },
  { name: "40+", uv: 6.08, fill: "#7eb8d4" },
];

export function Example() {
  return (
    <ResponsiveContainer width="100%" height={320}>
      <RadialBarChart
        cx="50%"
        cy="50%"
        innerRadius="18%"
        outerRadius="90%"
        barSize={12}
        data={data}
      >
        <RadialBar minAngle={15} background clockWise dataKey="uv" />
        <Legend
          iconSize={10}
          layout="vertical"
          verticalAlign="middle"
          align="right"
        />
        <Tooltip />
      </RadialBarChart>
    </ResponsiveContainer>
  );
}

Treemap

Rectangles sized by a number. Fine for a budget split, disk usage, that kind of breakdown. Nested data works if you have it; a flat list is enough. Color comes from fill on each item, not from a separate color scale.

Preview

Code

import { Treemap, Tooltip, ResponsiveContainer } from "recharts";

const data = [
  { name: "Frontend", size: 1200, fill: "#e8b84a" },
  { name: "Backend", size: 980, fill: "#5b9fd4" },
  { name: "Mobile", size: 740, fill: "#4db6a0" },
  { name: "Data", size: 610, fill: "#c9922e" },
  { name: "DevOps", size: 430, fill: "#7eb8d4" },
  { name: "Design", size: 290, fill: "#e07a5f" },
];

export function Example() {
  return (
    <ResponsiveContainer width="100%" height={320}>
      <Treemap
        data={data}
        dataKey="size"
        nameKey="name"
        stroke="#0a0c10"
        fill="#e8b84a"
      >
        <Tooltip />
      </Treemap>
    </ResponsiveContainer>
  );
}

SunburstChart

A pie chart with rings for each level of a tree: parents on the inside, children on the outside. Recharts is picky here. Every node needs a value, parents included (usually the sum of the kids), and unlike the other charts you have to pass width and height yourself.

Preview

Code

import { SunburstChart, Tooltip } from "recharts";

const data = {
  name: "Traffic",
  value: 1410,
  children: [
    {
      name: "Organic",
      value: 680,
      fill: "#e8b84a",
      children: [
        { name: "Blog", value: 420, fill: "#f0c65c" },
        { name: "Docs", value: 260, fill: "#c9922e" },
      ],
    },
    {
      name: "Paid",
      value: 490,
      fill: "#5b9fd4",
      children: [
        { name: "Search", value: 310, fill: "#7eb8d4" },
        { name: "Social", value: 180, fill: "#4a8ab8" },
      ],
    },
    {
      name: "Referral",
      value: 240,
      fill: "#4db6a0",
      children: [
        { name: "Partners", value: 150, fill: "#6fcbb8" },
        { name: "Newsletters", value: 90, fill: "#3a9a86" },
      ],
    },
  ],
};

export function Example() {
  return (
    <SunburstChart
      width={400}
      height={360}
      data={data}
      dataKey="value"
      fill="#e8b84a"
    >
      <Tooltip />
    </SunburstChart>
  );
}

Tooltip

Not a chart — it hangs off whatever you wrap it in. formatter is how you rename a series or add thousands separators. labelFormatter changes the heading in the hover box. cursor is that line that follows the mouse.

Preview

Code

import {
  LineChart,
  Line,
  XAxis,
  YAxis,
  CartesianGrid,
  Tooltip,
  ResponsiveContainer,
} from "recharts";

const data = [
  { name: "Jan", uv: 4000, pv: 2400 },
  { name: "Feb", uv: 3000, pv: 1398 },
  { name: "Mar", uv: 2000, pv: 9800 },
  { name: "Apr", uv: 2780, pv: 3908 },
  { name: "May", uv: 1890, pv: 4800 },
  { name: "Jun", uv: 2390, pv: 3800 },
];

export function Example() {
  return (
    <ResponsiveContainer width="100%" height={280}>
      <LineChart data={data}>
        <CartesianGrid strokeDasharray="3 3" />
        <XAxis dataKey="name" />
        <YAxis />
        <Tooltip
          cursor={{ stroke: "#e8b84a", strokeWidth: 1 }}
          formatter={(value, name) => [
            value.toLocaleString(),
            name === "uv" ? "Sessions" : "Page views",
          ]}
          labelFormatter={(label) => "Month: " + label}
        />
        <Line type="monotone" dataKey="pv" stroke="#5b9fd4" />
        <Line type="monotone" dataKey="uv" stroke="#e8b84a" />
      </LineChart>
    </ResponsiveContainer>
  );
}

Legend

Shows up under the chart unless you move it. If you don't set name on each Line or Bar, the legend will just say "pv" and "uv", which is useless. verticalAlign, align, and iconType are the knobs for placement and the little markers.

Preview

Code

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

const data = [
  { name: "Jan", uv: 4000, pv: 2400 },
  { name: "Feb", uv: 3000, pv: 1398 },
  { name: "Mar", uv: 2000, pv: 9800 },
  { name: "Apr", uv: 2780, pv: 3908 },
  { name: "May", uv: 1890, pv: 4800 },
  { name: "Jun", uv: 2390, pv: 3800 },
];

export function Example() {
  return (
    <ResponsiveContainer width="100%" height={280}>
      <BarChart data={data}>
        <CartesianGrid strokeDasharray="3 3" />
        <XAxis dataKey="name" />
        <YAxis />
        <Tooltip />
        <Legend
          verticalAlign="top"
          align="right"
          iconType="circle"
          height={36}
        />
        <Bar name="Page views" dataKey="pv" fill="#5b9fd4" />
        <Bar name="Sessions" dataKey="uv" fill="#e8b84a" />
      </BarChart>
    </ResponsiveContainer>
  );
}

That's the set

Swap the sample numbers for yours, tweak the colors, and you're most of the way to a dashboard. If you're still deciding on a library, start with how I pick a React JS graph library, then the Recharts page — or go poke around the rest of the list.

Latest posts

All posts

Cytoscape JS Examples

Cytoscape JS examples are node-link graphs, not bar charts. Here are four I actually paste: force, hierarchy, circle, and tap to highlight.

Cytoscape Examples Networks
Read post

Bar Charts Explained

A bar is a number you can compare at a glance. Here's when to use one, the four layouts I actually ship, and the mistakes that make a bar chart lie.

Charts Examples JavaScript
Read post