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

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

Charting & data visualization

reviewedconfidence: lowtrack: weakenedearly: 2/14 of this tier graded so far (0 overturned) — the public scorecard →

cited by: svg

re-verified 6× — 2026-08-18 · 2026-07-16 · 2026-07-13 · 2026-07-10 · 2026-07-09 · 2026-07-06 · 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).

  • realtime/finance RN charts → Skia-based (Victory Native XL, react-native-graph for scrubbing line charts, or react-native-livechart — the latter two newer/niche)
  • fully custom web viz → visx; quick standard charts → Recharts
  • heavy Skia/Reanimated perf → react-native-best-practices

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; mature, broad chart types382k/wk · ships in 2/34
react-native-gifted-chartsRN; declarative, quick to adopt148k/wk
react-native-skia (build-your-own)RN; max control + perf, more code
react-native-livechartRN; Skia + Reanimated + Gesture Handler; realtime/finance focus, crosshair scrubbing — newer/niche
react-native-graph (Margelo)RN; Skia-based LINE graphs with gesture scrubbing; REBOOTED v1.2 (2026-04) onto current Skia APIs after ~2y dormancy — line-focused, check it covers your chart types106k/wk
Recharts / visx / Chart.jsweb; visx = low-level D3 primitives (4.0.0), Recharts = batteries-included (3.10.1); both current as of 2026-08-18. The legacy web `victory` package is NOT one of these — it is dormant, see note49.9M/wk · ships in 5/34

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 382k · victory 415k · recharts 49.9M · chart.js 8.5M · react-native-gifted-charts 148k · react-native-graph 106k · d3-force 17.7M · d3 15.8M

Verified notes

Library picks are reasonable defaults but lightly vetted. Ignore react-native-livechart's satirical "degen mode" framing — not a selection axis. FRESHNESS (signals, 2026-07-10): the ACTIVE Victory line is victory-native XL (41.26, 2026-06, verified vs npm); d3's 2-year publish gap is maturity, not abandonment (it's the stable substrate under visx). CHALLENGED 2026-08-18 → WEAKENED (the RN default SURVIVED, one caveat was missing). The attack: react-native-gifted-charts ships weekly (1.4.78, 2026-08-10) and has more stars (1,362 vs 1,210), so should it take the RN default from Victory Native XL? No, on both axes this entry claims. DOWNLOADS: victory-native 381,672/wk vs gifted-charts 147,977/wk (2.6× the other way, verified vs the npm API) — the popularity argument runs backwards. SUBSTRATE: victory-native peers on @shopify/react-native-skia + Reanimated + Gesture Handler, gifted-charts on react-native-svg — so the entry's "Skia-backed for standard charts, raw Skia when you need custom/realtime" axis is a real rendering difference, not branding. Victory Native XL is slower-moving than it was (npm 41.26.0 2026-06-09, repo pushed 2026-07-06, 89 open issues) — watch it, but it is not stalled. WHAT THE CHALLENGE DID CHANGE: the web `victory` package is not "slow", it is DORMANT — npm 37.3.6 published 2025-01-14, repo last pushed 2025-12-19. Nothing here recommends it (web goes to Recharts 3.10.1 / visx 4.0.0, both current), but the option row read as though it were live, and its detect label shared the "victory" token with victory-native, which made `react-brain signals` report a dormant web package as a stale recommended DEFAULT. The label now says so explicitly, which is also the documented way to keep a row out of the default set.

Canonical reading

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

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 (41.26, 2026-06, verified against npm); the web victory package moves slowly. Judge the family by the XL line.

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. 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. The entry stakes no renderer claim for it; it wins on adoption speed, and that is the extent of what this page can say.

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.

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 slow-moving web victory package is not the active line — victory-native XL (41.26, 2026-06) 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, 41.26 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