react-chartjs-2

React components for Chart.js — typed, hooks-friendly charts for React apps

Library
npm
v5.3.1
6,936 stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum. How we score it →
68 /100 Good
Development Activity 52
Maintenance 44
Community 76
Maturity 60
Momentum 40

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation. How we score it →
85 /100 Excellent
Architecture 85
Code Quality 78
Innovation 88
Learning Curve 90

react-chartjs-2 wraps Chart.js in a small set of idiomatic React components so you can render line, bar, pie, doughnut, radar, and other chart types declaratively instead of imperatively managing a canvas instance yourself. It exposes both a generic Chart component and pre-typed shortcuts like Line, Bar, and Doughnut, each forwarding a ref to the underlying Chart.js instance for cases where you need direct imperative access (e.g. programmatic zoom or tooltip control). Under the hood it reconciles React’s declarative re-renders with Chart.js’s stateful, canvas-based rendering model using effect hooks, so passing new data or options props updates the existing chart in place instead of tearing down and rebuilding the canvas on every render.

It supports Chart.js v3 and v4, ships full TypeScript typings that propagate chart type, data point, and label generics through props, and has no runtime dependencies beyond chart.js and react as peer dependencies — keeping bundle size close to whatever Chart.js modules you register yourself.

What You Get

  • A generic Chart component plus pre-typed shortcuts (Line, Bar, Doughnut, Pie, Radar, PolarArea, Bubble, Scatter) that auto-register the matching Chart.js controller
  • Ref forwarding to the underlying Chart.js instance for imperative access (manual update(), plugin APIs, programmatic zoom)
  • In-place chart updates on prop changes (labels, datasets, options) instead of destroy-and-recreate on every render, using a dataset-id-aware diffing utility
  • Full TypeScript generics that carry chart type, data point shape, and label type through props for compile-time-checked chart configuration
  • Helper functions (getDatasetAtEvent, getElementAtEvent, getElementsAtEvent) for mapping canvas mouse events back to Chart.js dataset/element hits
  • Support for both Chart.js v3 and v4 with dedicated migration guides

Common Use Cases

  • Dropping a dashboard chart (line, bar, pie) into a React admin panel or analytics UI without hand-rolling canvas lifecycle management
  • Building interactive charts that respond to click/hover events by mapping canvas coordinates back to specific datasets or data points
  • Rendering charts whose data updates frequently (e.g. live metrics) where in-place updates avoid the flicker and cost of full chart teardown
  • Combining Chart.js plugins (zoom, annotation, date adapters) with a typed React wrapper instead of manipulating the Chart.js instance directly

Under The Hood

Architecture — The library’s entire runtime surface is four small files under src/: chart.tsx holds the core ChartComponent, which owns a canvasRef/chartRef pair and a cascade of useEffect hooks that translate prop changes (options, data.labels, data.datasets, type) into imperative Chart.js calls (chart.update(), or a full destroy/recreate via setTimeout(renderChart) when type or redraw changes) rather than re-instantiating a ChartJS object on every React render. typedCharts.tsx builds the named exports (Line, Bar, Doughnut, etc.) by calling ChartJS.register() with the matching controller and wrapping Chart in a forwardRef closure, so each named component is really the same ChartComponent pre-bound to a type and its required controller. utils.ts contains the dataset-reconciliation logic (setDatasets, cloneData) that matches incoming datasets to existing ones by a configurable datasetIdKey (default label) so in-place updates preserve Chart.js’s internal per-dataset animation/meta state instead of discarding it.

Tech Stack — Written in TypeScript against React’s forwardRef/hooks API with chart.js (^4.1.1) and react (^16.8.0 through ^19) as peer dependencies only — no other runtime dependencies. Built with Rollup (rollup.config.js) plus a separate tsc --emitDeclarationOnly pass for .d.ts output, and developed against Vite/Vitest tooling (vite.config.js) with Storybook 8 for the component playground published at website/.

Code Quality — test/chart.test.tsx (433 lines) covers rendering, ref forwarding, redraw behavior, and dataset/label update paths using @testing-library/react and vitest-canvas-mock to stub the canvas API; test/chart.test-d.tsx runs tsd type-level assertions to guard the exported generics. Source files are consistently typed (no any in the public surface), utility functions carry JSDoc comments, and ESLint (eslint-config-standard + React/Prettier plugins) plus a simple-git-hooks/nano-staged pre-commit setup enforce lint-clean, formatted commits. No integration tests against a real browser/canvas exist — all canvas interaction is mocked.

API Design — The public API is deliberately minimal: <Doughnut data={...} /> is a complete, working chart with no required boilerplate beyond passing data. Named chart components remove the need to manually call ChartJS.register() for common cases, while the generic Chart component and full TypeScript generics (ChartProps<TType, TData, TLabel>) are available when more control or an uncommon chart type is needed. The one piece of friction the docs call out repeatedly (via dedicated FAQ/migration pages) is that Chart.js v4’s tree-shakeable module registration model still leaks through for anything outside the pre-typed helpers, so consumers of less common configurations must understand Chart.js’s own controller/element/plugin registration to use the generic Chart component correctly.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers