react-brain
Browse decisions
React & language foundations 3App architecture 11UI 13Platform & native 9Build, test, observe, secure 6AI in React apps 3stack composerdecision recordscensusstaleness benchnewsletterarchitecturechangelogmethodologyroadmap

entriesui · verified 2026-10-08 · react + react-native

Charting & data visualization

reviewedconfidence: lowtrack: weakenedthis tier holds 64% on the public scorecard (7/14 graded · 0 overturned) →

related decisions: animation

cited by: animation · svg

re-verified 8× — 2026-10-08 · 2026-09-24 · 2026-09-21 · 2026-09-10 · 2026-09-01 · 2026-08-18 +2 · changelog

recommendation

RN: Victory Native (XL) for standard charts; react-native-skia when you need custom/realtime rendering. Web: Recharts (batteries-included) or visx (low-level D3). Skia-backed chart stacks stay on @shopify/react-native-skia (≤2.14) until Victory Native XL / livechart repoint to the renamed react-native-skia (RB-E-ANIMATION).

  • realtime/finance RN charts → Victory Native XL, else react-native-graph for scrubbing line charts, else react-native-livechart (all Skia-based; the latter two newer/niche)
  • RN app on Skia below 2.6.0 or Reanimated below 3.19.1 → Victory Native 41.x (pinned; 42 raises both floors)
  • RN team wanting the quickest declarative adoption without a Skia dependency → react-native-gifted-charts (SVG-rendered)
  • fully custom web viz → visx
  • quick standard web charts → Recharts
  • web charts from the TanStack stack with a 1.0 API contract → TanStack Charts (new; no adoption signal yet; RN support experimental)
  • existing Chart.js web code → Chart.js (keep it; this entry does not grade it against Recharts/visx)
  • heavy Skia/Reanimated perf → react-native-best-practices (owns render-perf depth)

Low confidence — fast-moving or lightly-vetted domain: treat the pick as a vetted lead and prototype before committing.

Options & tradeoffs

the field considered — and why each one isn’t the default here

optiontradeoffevidence
Victory Native (XL)RN; Skia-backed (peers @shopify/react-native-skia + Reanimated + Gesture Handler); mature, broad chart types. 42.0.1 (2026-08-31, verified vs npm 2026-09-24) is a floor-raise major: Skia >=2.6.0 <3.0.0 and Reanimated >=3.19.1; on older Skia/Reanimated stay on 41.x. See note: VICTORY NATIVE 42521k/wk · ships in 2/34
react-native-gifted-chartsRN; declarative, quick to adopt; renders through react-native-svg, not Skia (peer verified vs npm 2026-09-24; latest 1.4.78, 2026-08-10)286k/wk
react-native-skia (build-your-own)RN; max control + perf, more code. Now published as `react-native-skia` (3.x Graphite; v2 line as react-native-skia@2) — but Victory Native XL and react-native-livechart still peer on @shopify/react-native-skia, so a chart stack stays on the old name for now. See note: SKIA STEWARDSHIP
react-native-livechartRN; Skia + Reanimated + Gesture Handler; realtime/finance focus, crosshair scrubbing — newer/niche; 4.23.0 (2026-09-22, verified vs npm 2026-09-24) peers Reanimated >=4 and Skia >=2.6.0
react-native-graph (Margelo)RN; Skia-based LINE graphs with gesture scrubbing; rebooted at v1.2 (2026-04-15) onto current Skia APIs after ~2y dormancy and has shipped since (1.4.0, 2026-08-24, verified vs npm + releases 2026-09-24) — line-focused, check it covers your chart types23k/wk
Recharts / visx / Chart.jsweb; visx = low-level D3 primitives (4.0.0), Recharts = batteries-included (3.10.1), both current (verified vs npm 2026-09-24). Chart.js is carried for detection and not graded against them. The legacy web `victory` package is not one of these — it is dormant, see note: VICTORY (WEB)71.3M/wk · ships in 5/34
TanStack Charts (NEW, 1.0)web (and experimental RN): marks + scales + axes (grammar-of-graphics, Observable Plot lineage) from the org behind Query/Table/Router; 1.0.0 (2026-10-03, verified vs npm + the v1.0.0 release) is a compatibility contract for the documented public API; SVG by default, Canvas as a separate renderer; React via @tanstack/react-charts 1.0.0. React Native 'remains experimental' (optional peers react-native ^0.86 + react-native-svg 15.15.4+). No adoption signal yet. See note: TANSTACK CHARTS

evidence: npm weekly downloads (signals snapshot) · “ships in n/D” = adoption across the production-app census, honest denominators

npm weekly downloads (from the corpus's last signals run): victory-native 521k · victory 544k · recharts 71.3M · chart.js 15.7M · react-native-gifted-charts 286k · react-native-graph 23k · d3-force 28.6M · d3 26.0M

Verified notes

The durable axis is the RENDERER, not the chart menu. On React Native the picks draw through Skia on the GPU: Victory Native XL for standard charts, raw react-native-skia when you need custom/realtime rendering, so graduating from one to the other changes how much chart you hand-write, not what draws the pixels. On the web the division is D3 for math/layout while React owns the DOM; Recharts (batteries-included) and visx (low-level primitives) differ only in altitude. The library picks are reasonable defaults but lightly vetted, which is why confidence is low; ignore react-native-livechart's satirical "degen mode" framing — not a selection axis. VICTORY NATIVE 42 (42.0.0 2026-08-25, 42.0.1 2026-08-31; verified vs npm + GitHub): a FLOOR-RAISE major, not a feature release — minimum @shopify/react-native-skia >=2.6.0 (chart paths migrated to the immutable PathBuilder API) and minimum Reanimated >=3.19.1 → on older Skia/Reanimated stay on 41.x. SKIA STEWARDSHIP (2026-09-21, pointer — RB-E-ANIMATION owns this thread, its receipts and the tripwire): Shopify is leaving React Native, sponsors react-native-skia through the end of 2026, and its author forks the repo under a NEW NAME in the coming months, after which the Shopify repo is archived. Nothing is deprecated today (2.12.0 shipped 2026-09-16, after the announcement). The exposure here is broad rather than deep: Victory Native XL, react-native-graph and react-native-livechart all render THROUGH Skia, so a rename propagates to their peer ranges, not just to your own dependency list → pin across the transition window. 2026-10-08: the rename LANDED — `react-native-skia` 3.x (and @2 for the v2 line) — while victory-native 42.0.1 still peers @shopify/react-native-skia >=2.6.0 <3.0.0 and react-native-livechart 4.26.0 peers @shopify/react-native-skia >=2.6.0 (both verified vs npm), so those stacks hold the old name; react-native-graph 1.4.0 declares no Skia peer at all. DEFAULT CHALLENGED (2026-08-18, verified vs the npm API and GitHub): react-native-gifted-charts ships weekly (1.4.78, 2026-08-10) and had more stars (1,362 vs 1,210), so should it take the RN default? No, on both axes this entry claims. DOWNLOADS: victory-native 381,672/wk vs gifted-charts 147,977/wk (2.6× the other way). SUBSTRATE: victory-native peers on @shopify/react-native-skia + Reanimated + Gesture Handler, gifted-charts on react-native-svg, so "Skia-backed for standard charts, raw Skia for custom/realtime" is a real rendering difference, not branding. VICTORY (WEB) IS DORMANT (2026-08-18, verified vs npm + GitHub; npm re-checked 2026-09-24): npm 37.3.6 published 2025-01-14, repo last pushed 2025-12-19. Nothing here recommends it; its detect label says "dormant" because it shares the "victory" token with victory-native, which had made `react-brain signals` report a dormant web package as a stale recommended default. D3 FRESHNESS (signals, 2026-07-10): d3's 2-year publish gap is maturity, not abandonment — it is the stable substrate under visx. TANSTACK CHARTS LEAD (2026-09-10; 0.18.0 of 2026-09-10 verified vs npm + the v0.18.0 release 2026-09-24): @tanstack/charts is officially ALPHA (README badge and stability policy) and was called "ready to be field-tested" at 0.16 — a charting entrant from the org behind Query, Router, Table, Form and AI in this corpus; 0.18.0 adds renderer-neutral radial gradients with SVG and React Native fill support. NOT an option yet: alpha, no adoption signal; weigh it against the rows above at 1.0. 2026-10-08: 1.0.0 SHIPPED (2026-10-03, verified vs npm, the v1.0.0 release and Tanner Linsley's announcement): the release "establish[es] the TanStack Charts 1.0 compatibility contract for documented public APIs, extension protocols, framework support, and renderer behavior" and says "React Native remains experimental"; SVG is the default renderer with Canvas imported separately; no bundle figures were published. So it enters as a web option row, not the default: the stability contract is new, the adoption signal is still zero. HISTORY: 2026-10-08 REOPENED: TanStack Charts 1.0 (web option row; RN experimental); the Skia rename landed and Victory Native XL / livechart still peer on the @shopify name. 2026-09-01 CORRECTED: the "Victory Native XL is slower-moving — watch it" caveat from the 2026-08-18 challenge retired; v42 shipped two months after it. 2026-08-18 CHALLENGED → WEAKENED: the RN default (Victory Native XL over gifted-charts) survived on downloads and substrate; the web `victory` package was reclassified from slow to dormant.

Canonical reading

Editorial annotations on why each piece matters — the articles themselves are the originals; read them there.

Agentic Coding: Bet on the PrimitivesRobin Wieruch

The argument that most directly challenges how this entry (and every library-selection entry) is framed, made concrete on charts. Wieruch spiked the same design-system chart set twice in an hour — once on D3's math primitives with React rendering the SVG, once on Recharts with an identical component API — and the primitive version matched the design exactly (entrance animations, crosshair tooltips, legend filtering) while the Recharts version reached 80% faster and then hit a wall: the last 20% needed custom SVG anyway, and its entrance animation froze in that React stack with no fix but disabling it. His frame is worth borrowing: a high-level library is PREPAID IMPLEMENTATION LABOR, bought with flexibility — a primitive maps a value to a pixel and has no opinion about what you draw, a framework owns rendering, animation lifecycle and tooltips and hands you config props to negotiate with, and the difference only shows up when your requirements leave the author's assumptions. The claim is not that libraries lost; it is that agentic coding moved the CROSSOVER POINT toward primitives, so requirements that used to sit safely on the library side (three charts matching a design system, a bespoke form flow, a custom data grid) now often sit on the other. He argues the other side himself, and those caveats are the load-bearing part: a team without an established agentic workflow cannot place this bet, because the old labor math still applies to them; commodity UI on a library's happy path should stay there; every line you own is a line you maintain, without a community surfacing edge cases; deep-accessibility widgets (combobox, date picker, focus-managed modal) encode years of screen-reader testing not worth regenerating; and genuinely hard stable problems — date arithmetic, color interpolation, schema validation, floating-element positioning — stay dependencies. His last caveat is the sharpest: the spike worked because he could JUDGE the output, and an agent collapses the cost of writing a layer, not the cost of understanding it.

Introducing visx from AirbnbAirbnb Tech Blog

The architecture of web React charting — use D3 for math/layout while React owns the DOM, and compose low-level primitives instead of opinionated chart components. First-principles framing that applies to visx, Recharts, and any D3+React stack.

The Future of React Native Graphics: WebGPU, Skia, and BeyondWilliam Candillon (Shopify)

How RN Skia renders graphics — incl. the canonical high-density line-chart-as-GPU-texture example, JSI, immutable display lists, a unified WebGPU backend. The rendering model under Victory Native XL and build-your-own Skia charts.

Sources

Depth (in-domain rules) is owned by the react-native-best-practices skill — this entry is selection breadth.

The full explanation

The reviewed long-form essay behind this entry — the why, not a how-to. Also on GitHub.

About charting & data visualization

Diataxis: Explanation. This page builds understanding of the charting decision — why the durable axis is the renderer, not the chart catalogue. It is not a gallery tour and not an API guide. The candidate list and one-line tradeoffs live in the index entry RB-E-CHARTS; Skia/Reanimated render-performance depth is owned by the react-native-best-practices skill. The entry's own confidence is low — its note says the picks are reasonable defaults but lightly vetted — so read this as a map, then verify against your chart-type needs.

The one distinction that organises everything: pick the renderer, not the chart menu

A chart is a list wearing math. Underneath every bar, line, and candlestick there is a list of data points, a math/layout pass that turns data into geometry, and a renderer that draws the geometry. The two readings the index entry leans on describe exactly this split, once per platform:

  • Web: the visx architecture piece states the durable division of labor — D3 for math/layout while React owns the DOM, composing low-level primitives instead of opinionated chart components. That framing applies to visx, Recharts, and any D3+React stack.
  • React Native: the Shopify graphics piece gives the render model under the RN picks — Skia via JSI, immutable display lists, a unified WebGPU backend, with the canonical example being a high-density line chart rendered as a GPU texture.

So the real decision is which renderer draws your geometry — the DOM/SVG on web, the GPU via Skia on React Native — and how much of the math you want pre-packaged (batteries-included components vs low-level primitives). The chart menu — does the library's gallery have a donut? — is the least durable axis, because the math is a commodity (D3 on web) and the renderer is what a high-density realtime series lives or dies by — which is exactly why the canonical Skia example is a dense line chart rendered as a GPU texture.

The default, and why

RN: Victory Native (XL) for standard charts; react-native-skia when you need custom/realtime rendering. Web: Recharts (batteries-included) or visx (low-level D3).

On React Native both halves of the default sit on the same renderer: Victory Native XL is Skia-backed, mature, with broad chart types — and when its packaging runs out, build-your-own on react-native-skia buys maximum control and performance at the cost of more code. Graduating from one to the other changes how much chart you hand-write, not what draws the pixels.

On web the two picks share the D3+React division of labor and differ only in altitude: Recharts is batteries-included; visx is low-level D3 primitives for fully custom visualization. Pick by how bespoke the viz is, not by gallery screenshots.

The specialised when-clause is realtime/finance on RN: stay Skia-based — Victory Native XL, react-native-graph for scrubbing line charts, or react-native-livechart — with the honest caveat, from the entry itself, that the latter two are newer/niche.

The landscape, and when each one wins

Victory Native (XL) — the RN standard-charts default: Skia-backed, mature, broad chart types. One freshness fact matters when you audit it: the active Victory line is victory-native XL (42.0.1, 2026-08-31, verified against npm 2026-09-24); the web victory package is dormant (last publish 2025-01-14). Judge the family by the XL line. v42 is a floor-raise major: it needs @shopify/react-native-skia >=2.6.0 and Reanimated >=3.19.1 — on older versions stay on 41.x.

react-native-skia (build-your-own) — max control and max performance, more code. This is the "custom/realtime rendering" escape hatch, and the Shopify piece is its physics textbook: JSI, immutable display lists, WebGPU backend, line-chart-as-GPU-texture.

react-native-graph (Margelo) — Skia-based line graphs with gesture scrubbing. Its history is a lesson in reading release pages: rebooted at v1.2 (2026-04) onto current Skia APIs after roughly two years of dormancy, and it has kept shipping since (1.4.0, 2026-08-24). Line-focused — the entry's own instruction is to check it covers your chart types before adopting.

react-native-livechart — Skia + Reanimated + Gesture Handler; realtime/finance focus with crosshair scrubbing; newer and niche. The entry's note is explicit: ignore its satirical "degen mode" framing — that is not a selection axis.

react-native-gifted-charts — declarative and quick to adopt. It renders through react-native-svg, not Skia (its npm peer dependency), so it sits off the Skia axis: the pick when adoption speed matters more than a GPU renderer.

Recharts / visx / Chart.js (web) — Recharts batteries-included, visx low-level D3 primitives; Chart.js is listed in the same web group without a graded tradeoff. Beneath visx sits d3 itself, and its npm silhouette needs the same freshness literacy as Victory's: d3's 2-year publish gap is maturity, not abandonment — it is the stable substrate under visx.

Skia is changing hands (2026-09-21). Shopify is leaving React Native; react-native-skia's author will fork it under a new package name and the Shopify repo will be archived. Victory Native XL, react-native-graph and react-native-livechart all render through Skia, so the rename reaches their peer ranges too — pin Skia-backed chart stacks across the transition (RB-E-ANIMATION owns the thread).

Tradeoffs and failure modes to name out loud

  • Choosing from the chart menu. The gallery answers "can it draw a donut today"; the renderer answers "will it still be smooth with real data and realtime updates." The entry's when-clauses are renderer-shaped (realtime/finance → Skia-based), not gallery-shaped.
  • Adopting a scrubbing library, then needing a bar chart. react-native-graph is line-focused by design — the entry literally says to check it covers your chart types. The scrubbing demo is not a commitment to breadth.
  • Reading npm dates as health. Two opposite errors, both named in the entry's freshness note: d3's 2-year gap is maturity, not abandonment; and the dormant web victory package is not the active line — victory-native XL (42.0.1, 2026-08-31) is. Publish cadence only means something relative to a library's role in the stack.
  • Dormancy that did matter. react-native-graph sat dormant for ~2 years before its v1.2 (2026-04) reboot onto current Skia APIs — for Skia-adjacent libraries, "does it target the current Skia era" is a real compatibility question, not paranoia.
  • Marketing noise as signal. react-native-livechart's satirical "degen mode" framing is not a selection axis — evaluate the stack (Skia + Reanimated + Gesture Handler, crosshair scrubbing) and the newer/niche maturity, not the bit.
  • Trusting this page too much. Confidence here is low by the entry's own admission: the picks are reasonable defaults, lightly vetted. Verify chart-type coverage and freshness against npm before committing.

How it interacts with the rest of the stack

  • Render performance (react-native-best-practices). The defer skill: heavy Skia/Reanimated performance discipline lives there. This page owns which renderer and which library; that skill owns keeping the frames.
  • Animation & gestures (RB-E-ANIMATION). The realtime RN options are built from the animation stack's parts — react-native-livechart is explicitly Skia + Reanimated + Gesture Handler, and gesture scrubbing is the headline feature of react-native-graph. Interactive charts are animation surfaces.
  • SVG (RB-E-SVG). The web half of the renderer axis. The D3+React division — D3 for math/layout, React owning the document — is the same architecture whether the primitives are a chart library's or your own.
  • Lists (RB-E-LISTS). The "lists wearing math" lens is literal at high density: a realtime series is list-scale data on a render budget, which is exactly why the canonical Skia example is a high-density line chart as a GPU texture.

In one paragraph

Charts are lists wearing math: data, a math/layout pass, and a renderer — and the renderer is the durable axis. On web, D3 does math/layout while React owns the DOM (Recharts batteries-included, visx low-level primitives; d3's 2-year publish quiet is maturity, not abandonment). On React Native the renderer is Skia on the GPU — JSI, immutable display lists, a WebGPU backend, high-density line charts as GPU textures — under both the default (Victory Native XL, 42.x active line) and the escape hatch (build-your-own react-native-skia). Realtime/finance stays Skia-based via react-native-graph (line-focused, rebooted v1.2 2026-04 after ~2y dormancy — check chart-type coverage) or react-native-livechart (newer/niche; ignore the satirical framing). Pick by renderer and altitude, verify the lightly-vetted specifics against npm, and take Skia/Reanimated performance depth from react-native-best-practices.


See also: RB-E-SVG (the web renderer under D3+React stacks), RB-E-ANIMATION (Reanimated + Gesture Handler, the substrate of scrubbing charts), RB-E-LISTS (high-density data on a render budget). Performance depth: the react-native-best-practices skill. Background reading: Airbnb's visx introduction (D3 for math, React for the document) and William Candillon's RN graphics deep-dive (the Skia/WebGPU render model).

Related in ui: styling · component-libs · animation · lists · a11y · i18n · editors · svg · maps · calendars · sheets · polish