react-native-graphify
v1.1.0
Published
Skia-powered charts for React Native. 15+ chart types with a UI-thread touch cursor, pan/zoom, streaming, drilldown, statistical series and a real screen-reader layer. No WebView, one API for iOS and Android.
Readme
react-native-graphify
Skia-powered charts for React Native. Native performance, no WebView, one API for iOS and Android.
Status: 1.1.0. All 27 phases of the v1 roadmap are complete — cartesian and polar series, interaction, streaming, drilldown, annotations, statistical series and a screen-reader layer — plus a Highcharts-style options API. Semver applies: breaking API changes mean 2.0.0. See What's not done before adopting.
Install
npm install react-native-graphifyPeer dependencies you must already have:
npx expo install @shopify/react-native-skia react-native-reanimated react-native-worklets react-native-gesture-handlerSkia does not run in Expo Go — you need a development build.
Your first chart
import { Area, Chart, Grid, XAxis, YAxis } from 'react-native-graphify';
const data = [
{ month: 'Jan', revenue: 210 },
{ month: 'Feb', revenue: 340 },
{ month: 'Mar', revenue: 180 },
{ month: 'Apr', revenue: 420 },
];
export function Revenue() {
return (
<Chart data={data} xKey="month" yKeys={['revenue']} height={220}>
<Grid />
<YAxis />
<XAxis />
<Area seriesKey="revenue" />
</Chart>
);
}Add a touch cursor with a tooltip:
<Chart data={data} xKey="month" yKeys={['revenue']} cursor haptics overlay={<Tooltip />}>
<Grid />
<YAxis />
<XAxis />
<Area seriesKey="revenue" />
<Crosshair />
</Chart>Or: Highcharts-style options
Already have Highcharts configs? Pass the same object shape to <Graphify>:
import { Graphify } from 'react-native-graphify';
import type { GraphifyOptions } from 'react-native-graphify';
const options: GraphifyOptions = {
chart: { type: 'line', height: 400 },
title: { text: 'Monthly Sales' },
xAxis: { categories: ['Jan', 'Feb', 'Mar', 'Apr'] },
tooltip: { valuePrefix: '₹' },
plotOptions: { line: { dataLabels: { enabled: true } } },
series: [{ name: 'Sales', data: [12000, 18000, 15000, 22000] }],
};
<Graphify options={options} />;It covers a typed subset of Highcharts — see Options API.
What it does today
| Series | Status |
| --- | --- |
| Line — linear, monotone, step, stepAfter | ✅ |
| Area — eased gradient fill, configurable baseline | ✅ |
| Column — grouped, rounded outer corners, minBarLength | ✅ |
| Scatter — circle, square, diamond | ✅ |
| Bubble — sqrt radius so area encodes magnitude | ✅ |
| Pie, donut, semi-circle, arbitrary angles | ✅ |
| Radar — with independentAxes per spoke | ✅ |
| Wind rose — stacked polar columns | ✅ |
| Gauge and activity rings | ✅ |
| Area range, dumbbell, error bars | ✅ |
| Box plot — tukey/minmax/stddev whiskers, notches, outliers | ✅ |
| Waterfall, histogram, pareto, bell curve | ✅ |
| Streaming — ring-buffered, 60 appends/sec without a re-render | ✅ |
| Feature | Status |
| --- | --- |
| Axes, grid, smart ticks, label collision resolution | ✅ |
| Touch cursor, crosshair, tooltip, haptics — all on the UI thread | ✅ |
| Pinch-zoom and pan with momentum and rubber-banding | ✅ |
| Drilldown with breadcrumbs and Android back handling | ✅ |
| Plot lines, plot bands and callout annotations | ✅ |
| Screen-reader layer, data table, pattern fills | ✅ |
| Gradients — linear, radial, sweep — on any series | ✅ |
| Legend with tap-to-toggle | ✅ |
| Theme system, light/dark, three CVD-verified palettes | ✅ |
| Decimation (LTTB, min/max) and hit-testing | ✅ |
| Missing-data policies — gap, connect, zero | ✅ |
Why not react-native-svg?
An SVG chart creates one native view per element. A 500-point line is 500 views that React must reconcile and the platform must lay out, every update. Skia draws the same line as a single path into one canvas.
That difference is why this library batches aggressively: every grid line of one
orientation is a single SkPath, every bar of a series is a single SkPath,
every scatter point of a series is a single SkPath. At 200 bars that is the
difference between one draw call and two hundred.
Honest comparison
| | react-native-graphify | gifted-charts | victory-native XL | chart-kit | | --- | --- | --- | --- | --- | | Renderer | Skia | react-native-svg | Skia | react-native-svg | | Chart types | 7 today | ~15 | ~8 | ~6 | | Web support | Planned (v3) | No | No | No | | Maturity | Pre-release | Mature | Mature | Mature, low activity | | Bundle (gzipped) | ~55 kB | — | — | — |
Use gifted-charts today if you want breadth and stability right now — it has far more chart types and years of production use. Use victory-native XL if you want a Skia renderer from a maintained project with a real user base. This library is younger than both; its bets are the pure-TypeScript core (which makes a web renderer an adapter rather than a rewrite) and interaction that never touches the JS thread.
Performance
Measured in Node on an Apple Silicon laptop. These are not device numbers — device benchmarks in release builds on a mid-range Android phone are still outstanding, and publishing laptop numbers as device numbers is how benchmark tables lose their credibility.
| Operation | Measured | Roadmap target |
| --- | --- | --- |
| LTTB, 100k → 800 points | 0.32 ms | < 15 ms |
| Hit-test (x mode), 100k points | 0.0002 ms | < 0.1 ms |
| clipToViewport, 1M points | 0.0001 ms | — constant, proving it returns a view not a copy |
| Quadtree build, 50k points | 6.4 ms | once per data change, not per frame |
Run them yourself: yarn bench.
Architecture
One package, three layers:
| Directory | What it is |
| --- | --- |
| src/core | Renderer-agnostic maths. Pure TypeScript, zero React Native, runs in plain Node. |
| src/skia | Skia renderer adapter. |
| src/charts | The components you import. |
src/core having no React Native dependency is not a style choice. Every
renderer is an adapter over it, which is why a web renderer stays adapter work
rather than a rewrite — the same reason victory-native had to drop web parity
when it moved to Skia. A lint rule fails the build if anything under
src/core imports React Native, so the boundary is enforced rather than
merely intended.
Documentation
- Getting started
- Options API (Highcharts-style)
- Chart types
- Interaction
- Accessibility
- Theming
- Performance
- Why not SVG?
- Architecture
What's not done
Being explicit, because a feature table that hides gaps costs more trust than it buys:
- No device benchmarks. Only Node numbers exist. Everything is verified on the Android emulator and the iOS simulator, not on physical hardware.
- The screen-reader layer has not had a real VoiceOver/TalkBack listening pass. The accessibility trees were dumped and checked on both platforms — labels, values and traversal order are correct — but reading a tree is not the same as navigating one.
- No screenshot regression tests. See docs/screenshot-testing.md for why the tool the roadmap named is not usable.
- No plugin architecture (v2.0.0). The Highcharts-style options API covers a typed subset of Highcharts, not all of it.
- No financial module, heatmaps, treemaps, maps, Gantt or web renderer — roadmap phases 28–41.
- Pie and scatter are partial — no slice explode, connector labels, quadtree-backed tap targets or trend lines yet.
Development
Requires Node 20+. Yarn 4 comes from Corepack.
corepack enable
yarn install
yarn build && yarn test && yarn lint && yarn typecheckRun the example app (needs a dev client — Skia does not run in Expo Go):
yarn example:ios # or yarn example:android
yarn example # fast loop once a dev client is installedMetro resolves react-native-graphify to workspace source, so editing src/
hot-reloads the app with no rebuild.
| Script | Does |
| --- | --- |
| yarn build | Builds the library with builder-bob. |
| yarn test | Jest. |
| yarn bench | Performance benchmarks. |
| yarn size | Bundle budgets (needs a build first). |
| yarn lint / yarn typecheck / yarn format | Quality gates. |
| yarn prepublish:check | Verifies everything before a release. |
Licence
MIT
