Every dashboard starts with a bar chart and ends with a crisis. The first chart takes an afternoon. Six months later, the dashboard has twenty visualizations, the tooltip library is fighting the animation library, and your bundle is a slow, janky monster that product managers screenshot on good days and curse on bad ones. The root cause is almost always the same: the charting library was picked for a single chart, not for the next three years of dashboards. In 2026 the React ecosystem has three serious contenders — recharts (27,509 stars), visx (21,007 stars), and react-chartjs-2 (6,941 stars) — and they represent three completely different philosophies of how to build visualizations.

Here is the uncomfortable part most tutorials skip: these libraries do not just differ in API style. They differ in rendering strategy (SVG vs canvas), in who owns the chart (a component library vs a toolkit of primitives vs a thin React wrapper around Chart.js), and in how much you will fight them for custom interactions. Get that decision wrong and you do not rewrite a chart — you rewrite the dashboard. This guide compares all three with real code, real stats, and a decision matrix, so you pick once and never revisit it.

TL;DR — Quick Verdict

If you want charts working today with the least code and the best default look, pick recharts — its declarative components (<LineChart>, <BarChart>) are the fastest path from data to a professional chart, and it is the most popular choice in the React ecosystem for a reason. If you are building custom, highly interactive visualizations (brushing, linked charts, bespoke axes, zoom) and you are comfortable composing low-level primitives, pick visx — it is the toolkit behind Airbnb’s data products. If you are migrating an existing Chart.js codebase or you need the full chart.js feature set (canvas rendering, 100+ chart types, animations) without learning a new mental model, pick react-chartjs-2. For 80% of business dashboards, recharts is the correct default; visx is the power-user choice; react-chartjs-2 is the pragmatic migration path.

Quick Comparison Table

Featurerechartsvisxreact-chartjs-2
TypeDeclarative chart componentsLow-level visualization primitivesReact wrapper around Chart.js
GitHub stars27,50921,0076,941
LicenseMITMITMIT
Last push2026-08-192026-06-222026-08-14
RenderingSVGSVG (+ canvas via vx)Canvas
Bundle approachOne package~30 granular packages (@visx/xychart, @visx/scale…)react-chartjs-2 + chart.js
Learning curveGentleSteepModerate (Chart.js docs transfer)
Custom interactionsModerate (events, custom shapes)Full control (compose your own chart)Via Chart.js plugins/options
AccessibilityDecent defaults (roles/aria on some charts)You build itRequires Chart.js config work
Best forBusiness dashboards, admin panelsData-viz products, bespoke chartsMigrating Chart.js apps, canvas-heavy needs
MaintenanceVery activeActiveMaintained (Chart.js v4 ecosystem)

Use Case Decision Matrix

Use CaseRecommended ToolWhy
Admin dashboard, need professional charts fastrechartsDeclarative components + responsive container = minutes to first chart
Highly custom visualization (linked brushing, custom axes)visxScale, shape, and interaction primitives you compose yourself
Existing Chart.js app, want React bindingsreact-chartjs-2Same chart.js config, same options, React component wrapper
Huge datasets (100k+ points) that kill SVG performancereact-chartjs-2 (canvas)Canvas rendering handles density far better than SVG DOM nodes
App already uses Airbnb-style design-system data productsvisxBuilt by the Airbnb visualization team, matches that ecosystem
Team is React beginners, timeboxed deliveryrechartsLeast ceremony; sensible defaults out of the box
Charts inside tables or tiny widgetsrechartsTiny <Line> sparkline components with ResponsiveContainer
Need tree maps, sankey, radar, and 100+ other typesreact-chartjs-2Chart.js ships more chart types than any component library

recharts — The Declarative Default

recharts calls itself a “Redefined chart library built with React and D3.” The pitch is honest: it borrows D3’s scales and math but wraps everything in declarative React components, so you never touch D3’s imperative API. A line chart is a composition of components that reads like a blueprint:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import {
  LineChart, Line, XAxis, YAxis, CartesianGrid,
  Tooltip, Legend, ResponsiveContainer
} from 'recharts';

const data = [
  { month: 'Jan', revenue: 4200, costs: 3100 },
  { month: 'Feb', revenue: 5100, costs: 3400 },
  { month: 'Mar', revenue: 5800, costs: 3600 },
];

export function RevenueChart() {
  return (
    <ResponsiveContainer width="100%" height={320}>
      <LineChart data={data}>
        <CartesianGrid strokeDasharray="3 3" />
        <XAxis dataKey="month" />
        <YAxis />
        <Tooltip />
        <Legend />
        <Line type="monotone" dataKey="revenue" stroke="#6366f1" strokeWidth={2} />
        <Line type="monotone" dataKey="costs" stroke="#f59e0b" strokeWidth={2} />
      </LineChart>
    </ResponsiveContainer>
  );
}

The ResponsiveContainer wrapper is a small but decisive feature: it measures its parent and rescales the chart automatically, which kills the classic “chart renders at 0px inside a flex container” bug that plagues manual-resize approaches. recharts also gives you the chart types business dashboards actually need out of the box — line, area, bar, pie, scatter, radar, radial bar, treemap, and composable combinations via <ComposedChart> — plus animations, tooltips, legends, and a theming API via Customized.

The trade-offs are real. recharts renders SVG, so very large datasets (tens of thousands of points) degrade into a DOM-node nightmare; you work around it with data downsampling or by dropping to canvas. Custom interactions beyond what the library provides (crosshair brushing, linked charts) require reaching into Customized components or fighting the abstraction. And its D3 heritage means the package pulls in D3-scale and D3-shape dependencies, though tree-shaking keeps the practical bundle reasonable. For the mainstream dashboard use case, none of that matters — recharts is the fastest path from JSON to a chart your stakeholders call “beautiful.”

visx — The Visualization Toolkit

visx (“visualization components”) is not a chart library; it is a collection of low-level primitives built by the Airbnb visualization team. Instead of <LineChart>, you get @visx/scale (D3 scales as React-friendly helpers), @visx/shape (lines, areas, curves, paths), @visx/axis, @visx/grid, @visx/event, @visx/tooltip, @visx/zoom, @visx/brush, and about twenty more packages. You compose them into exactly the chart you need, and no more:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
import { XYChart, LineSeries, Axis, Tooltip } from '@visx/xychart';

const data = [
  { date: '2026-01-01', value: 42 },
  { date: '2026-02-01', value: 55 },
  { date: '2026-03-01', value: 49 },
];

export function VisxLineChart() {
  return (
    <XYChart height={320} xScale={{ type: 'band' }} yScale={{ type: 'linear' }}>
      <Axis orientation="bottom" />
      <Axis orientation="left" />
      <LineSeries dataKey="value" data={data} stroke="#10b981" strokeWidth={2} />
      <Tooltip snap="x" showDatumGlyph />
    </XYChart>
  );
}

@visx/xychart is the closest thing visx has to a ready-made chart, added to make the toolkit more approachable; the rest of the ecosystem remains deliberately composable. This is where visx wins decisively: if your product needs brushing linked across two charts, a custom scale, animated transitions between states, or a chart shape no library ships, visx gives you the primitives to build it without fighting an abstraction layer. Airbnb uses it in production for exactly these scenarios, and the @visx/zoom and @visx/brush packages are the most robust open-source implementations of those interactions in the React ecosystem.

The cost is everything the previous sentence implies. You assemble your own chart: axes, grids, tooltips, legends, and responsive behavior are all on you (or borrowed from examples). The learning curve is steep, and the granular packages mean dependency management is more involved (though the @visx/xychart entry point reduces that). If your team ships a dashboard in two weeks, visx will not hold your hand. If you are building a data product that will be customized for years, visx is the investment that pays off — the code you write composes cleanly instead of being replaced when the requirements change.

react-chartjs-2 — The Pragmatic Bridge

react-chartjs-2 does exactly one thing: it wraps the most popular charting library in the JavaScript ecosystem, Chart.js, in a React component layer. You write Chart.js configuration objects — the same options, scales, and plugins you would use in vanilla Chart.js — inside React components:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
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);

const data = {
  labels: ['Jan', 'Feb', 'Mar'],
  datasets: [
    {
      label: 'Revenue',
      data: [4200, 5100, 5800],
      borderColor: 'rgb(99, 102, 241)',
      tension: 0.3,
    },
  ],
};

export function ChartJsLine() {
  return <Line data={data} options={{ responsive: true, maintainAspectRatio: false }} />;
}

Chart.js v4’s tree-shakeable architecture means you register only the components you use — that is the ChartJS.register(...) call above, which also keeps the bundle lean compared to importing the whole library. Chart.js renders to canvas, which gives it a decisive performance advantage over SVG-based libraries on dense datasets; a scatter plot with 100,000 points is genuinely usable in Chart.js where recharts or visx would choke the DOM.

The wrapper’s own docs describe it as a thin layer, and that is both the strength and the limitation. You get every Chart.js feature — 100+ chart types via the plugin ecosystem (tree maps, sankeys, gauges), animations, interactions, decimation for big data — because you are just writing Chart.js. But you also get Chart.js’s quirks: options are plain objects rather than typed React props, React StrictMode double-rendering has historically needed care with chart instances, and the component lifecycle (ref access to the underlying chart) is occasionally awkward. If you already know Chart.js or you are migrating an existing app, it is the lowest-risk choice; if you want idiomatic React components, recharts feels more native.

Pitfalls and Gotchas — What Nobody Tells You

1. SVG vs canvas is not a minor detail — it is the scalability ceiling. recharts and visx render SVG: every data point becomes a DOM node, so tooltips and styling are easy, but 10,000+ points degrade interactivity. Chart.js renders canvas: dense datasets stay fast, but you lose per-element DOM styling and accessibility hooks. Pick based on your data size today and in two years, not on which demo looks prettier.

2. ResponsiveContainer inside flex/grid parents. recharts’ responsive wrapper measures the parent element, and if that parent is a flex item without a definite height, the chart collapses to zero height. The fix is a wrapper div with explicit height/width or min-height — the classic “chart is invisible until I resize the window” bug.

3. Tooltips and portals in tables/overflow containers. All three libraries render tooltips inside the chart container by default. Inside a scrollable table or an overflow: hidden card, tooltips get clipped. Plan a portal or render tooltips in a fixed-position layer before you need it, not after.

4. Version skew in the visx monorepo. visx publishes dozens of packages with independent versions. Mixing @visx/xychart@3 with an older @visx/scale@2 produces subtle type errors. Keep visx packages on one major version and use npm ls @visx/* in CI to catch drift.

5. Chart.js registration is global and easy to get wrong. Forgetting to register CategoryScale or LinearScale results in cryptic “category is not a registered scale” errors. Centralize ChartJS.register(...) in one module that your whole app imports — do not sprinkle registrations across components.

6. Animation libraries fighting chart libraries. If you animate chart containers with framer-motion or similar, the chart libraries’ own entrance animations double up, causing jank and duplicated work. Disable chart entrance animation (isAnimationActive={false} in recharts, animation: false in Chart.js) and animate the wrapper instead. Our JavaScript animation libraries guide covers the animation side of this trade-off.

7. Locale and number formatting. None of the libraries format axis ticks the way your finance team wants by default. Budget time for tick formatters (currency, thousands separators, locale-aware dates) — this is where dashboards quietly look “off” to stakeholders. The JavaScript datetime libraries comparison helps for the date half of this.

For the surrounding React stack, our component library comparison and data fetching guide cover the UI and server-state layers a dashboard sits on, and the state management comparison handles client state for chart filters and selections.

FAQ

By GitHub stars, recharts leads with 27,509, followed by visx at 21,007 and react-chartjs-2 at 6,941. Popularity is a proxy for ecosystem health: more stars means more contributors, more examples, and more answered questions. For mainstream dashboard work, recharts’ popularity is self-reinforcing — the problem you hit is almost certainly documented.

Can I use recharts for large datasets?

recharts renders SVG, so tens of thousands of points degrade performance. Options: downsample server-side or client-side (e.g., decimation or LTTB), aggregate to time buckets, or switch to canvas-based react-chartjs-2 for genuinely huge datasets. For 1-5k points — the common dashboard range — recharts is fine.

Is visx harder to learn than recharts?

Yes, intentionally. visx is a toolkit of primitives (scales, shapes, axes, zoom, brush), so you compose charts yourself; recharts gives you ready-made <LineChart>/<BarChart> components. Use visx when you need custom interactions and bespoke charts, recharts when you want results fast. The @visx/xychart package softens the learning curve with a higher-level API.

Does react-chartjs-2 work with React 19 and TypeScript?

Yes. react-chartjs-2 v5 supports React 19 and ships TypeScript types for the wrapper components; the underlying Chart.js v4 is framework-agnostic and actively maintained (last push August 2026). Check the peer-dependency range when upgrading React majors, since wrapper libraries occasionally lag.

How do I make charts responsive without breaking layout?

Use recharts’ ResponsiveContainer with an explicit-height wrapper div, or options.responsive: true with maintainAspectRatio: false in Chart.js. visx requires manual measurement (or the @visx/responsive useParentSize hook). The common failure is a flex parent with no definite height — always give the chart a concrete container height.

Which library is best for a time-series dashboard?

For standard time-series (line/area charts with date axes), recharts is the fastest to ship and looks polished. For dashboards needing linked brushing, cross-filtering, or custom time axes, visx’s @visx/brush and scale primitives are the strongest. Both handle time scales via D3 under the hood; recharts hides it, visx exposes it.

Do these libraries support dark mode and theming?

recharts supports custom colors per component and a Customized theming layer; Chart.js uses global defaults you can override for dark backgrounds; visx leaves theming to your design tokens since you compose everything. For multi-theme dashboards, centralize color definitions (CSS variables work well) and pass them as props/options rather than hard-coding hex values in every chart.

Which library should a beginner React developer choose?

recharts. Its declarative component model matches React’s mental model, the default styling looks professional, and ResponsiveContainer removes the hardest layout problem. Beginners should avoid visx until they need its primitives, and react-chartjs-2 requires learning Chart.js’s option-object model alongside React.


💰 想测试你的市场判断力?我用 Polymarket 做预测市场交易——这是全球最大的预测市场平台,从大选结果到技术监管时间线,什么都可以押注。和赌博不同,这是真正的信息市场:你懂的信息越多,胜率越高。我靠预测技术相关事件的走向已经赚了不少。用我的邀请链接注册:Polymarket.com