Description:
React Native Financial Charts is a charting library for React Native that renders financial data using Skia and Reanimated.
It executes all animations and gesture handling on the UI thread. This means your charts maintain 60 or 120 FPS even during complex touch interactions.
Features
- 🚀 GPU Rendering: Skia draws all chart elements directly on the GPU, bypassing the React Native bridge for visual updates.
- 👆 UI Thread Gestures: Touch handlers run as worklets, so dragging and tapping never block JavaScript execution.
- 🎯 Pixel-Perfect Cursor: The hybrid lookup table and Catmull-Rom algorithm snaps the cursor dot exactly to the data line at every frame.
- 🎨 Full Visual Control: Stroke width, gradient colors, tooltip styles, and container dimensions accept custom values.
- 📊 Composable Structure: The
Chart.Root,Chart.Canvas,Chart.Line,Chart.Area, andChart.Cursorcomponents nest logically like any React tree. - 💱 Custom Formatters: Worklet functions format currency, percentages, or dates without crossing the JS bridge.
- 📉 Baseline Indicator: A dashed horizontal line marks the starting value for quick profit/loss visualization.
Preview
Use Cases
- Crypto Portfolio Apps: Display live Bitcoin or Ethereum price charts with color-coded lines matching each asset’s brand identity.
- Stock Trading Interfaces: Render intraday or historical stock data with tooltips showing exact prices at each timestamp.
- Sparkline Widgets: Embed minimal 60×120 pixel charts inside list rows or ticker cards without tooltips or padding.
- Financial Dashboards: Combine multiple charts on a single screen while maintaining smooth scrolling and gesture response.
How to Use It
Install the Package and Peer Dependencies
The library requires Skia, Reanimated, Gesture Handler, and D3 as peer dependencies. Run these commands in your project directory:
yarn add react-native-financial-charts
yarn add @shopify/react-native-skia react-native-reanimated react-native-gesture-handler d3If you use Expo, switch to a development build instead of Expo Go. Run npx expo run:android or npx expo run:ios to compile the native modules.
Configure Babel for Reanimated
Open babel.config.js and add the Reanimated plugin to the plugins array:
module.exports = {
presets: ['module:metro-react-native-babel-preset'],
plugins: ['react-native-reanimated/plugin'],
};This step enables worklet compilation. Without it, gesture handlers and formatters will throw errors.
Wrap Your App with GestureHandlerRootView
The gesture handler requires a root wrapper at the top of your component tree:
import { GestureHandlerRootView } from 'react-native-gesture-handler';
export default function App() {
return (
<GestureHandlerRootView style={{ flex: 1 }}>
{/* Your screens go here */}
</GestureHandlerRootView>
);
}Render a Basic Chart
Import the Chart component and pass an array of data points. Each point needs a timestamp (milliseconds since epoch) and a value (numeric):
import React from 'react';
import { View } from 'react-native';
import { Chart } from 'react-native-financial-charts';
import { GestureHandlerRootView } from 'react-native-gesture-handler';
const priceData = [
{ timestamp: 1625945400000, value: 33575.25 },
{ timestamp: 1625946300000, value: 33545.25 },
{ timestamp: 1625947200000, value: 33510.25 },
{ timestamp: 1625948100000, value: 33215.25 },
{ timestamp: 1625949000000, value: 33450.00 },
];
export default function PriceChart() {
return (
<GestureHandlerRootView style={{ flex: 1 }}>
<View style={{ flex: 1, backgroundColor: '#0D0D0D', paddingTop: 100 }}>
<Chart.Root data={priceData} height={280}>
<Chart.Canvas>
<Chart.Area gradientColors={['#00E39650', '#00E39600']} />
<Chart.Line strokeWidth={3} colors={['#00E396']} />
<Chart.Cursor crosshairColor="#FFFFFF" circleColor="#00E396" />
</Chart.Canvas>
<Chart.Tooltip.Value />
<Chart.Tooltip.Date />
</Chart.Root>
</View>
</GestureHandlerRootView>
);
}The Chart.Root component calculates scales and manages shared state. Inside Chart.Canvas, you compose Chart.Area, Chart.Line, and Chart.Cursor in any order. Tooltips sit outside the canvas and update reactively as the cursor moves.
Apply Custom Currency Formatting
Define a worklet function to format the tooltip value. The 'worklet' directive at the top of the function body tells Reanimated to run this code on the UI thread:
const formatBTC = (value: number) => {
'worklet';
return `â‚¿ ${value.toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 })}`;
};
// Inside your chart
<Chart.Tooltip.Value format={formatBTC} />Create a Sparkline for List Items
Strip away tooltips, cursors, and padding to create a compact chart:
<Chart.Root data={priceData} height={50} width={100} padding={0}>
<Chart.Canvas>
<Chart.Line strokeWidth={1.5} colors={['#10B981']} />
</Chart.Canvas>
</Chart.Root>This configuration fits inside table cells or horizontal scroll views.
Show a Baseline for Profit/Loss
Add the Chart.Baseline component to draw a dashed line at the first data point’s value:
<Chart.Canvas>
<Chart.Baseline color="#858CA2" showLabel={true} />
<Chart.Area gradientColors={['#00E39650', '#EA394350', '#EA394350', '#00E39600']} />
<Chart.Line colors={['#00E396', '#00E396', '#EA3943', '#EA3943']} />
<Chart.Cursor />
</Chart.Canvas>The gradient and line colors shift from green above the baseline to red below it.
API Reference
Chart.Root
| Prop | Type | Default | Description |
|---|---|---|---|
data | { timestamp: number, value: number }[] | Required | Array of data points with Unix timestamps in milliseconds |
height | number | 250 | Total height of the chart in pixels |
width | number | Screen width | Total width of the chart in pixels |
padding | number | 20 | Horizontal padding inside the chart boundaries |
containerStyle | ViewStyle | {} | Style object applied to the outer container view |
Chart.Canvas
| Prop | Type | Default | Description |
|---|---|---|---|
children | React.ReactNode | None | Skia-compatible child components only |
Chart.Line
| Prop | Type | Default | Description |
|---|---|---|---|
strokeWidth | number | 3 | Thickness of the line in pixels |
colors | string[] | ['#00E396', '#00E396', '#EA3943', '#EA3943'] | Gradient color stops from top to bottom |
Chart.Area
| Prop | Type | Default | Description |
|---|---|---|---|
gradientColors | string[] | ['#000', '#000', '#000', '#000'] | Four color stops for the area gradient |
Chart.Cursor
| Prop | Type | Default | Description |
|---|---|---|---|
crosshairColor | string | 'white' | Color of the vertical crosshair line |
circleColor | string | 'white' | Border color of the cursor circle indicator |
Chart.Baseline
| Prop | Type | Default | Description |
|---|---|---|---|
color | string | '#858CA2' | Color of the dashed baseline and starting dot |
showLabel | boolean | true | Toggles visibility of the formatted value chip |
Chart.Tooltip.Value
| Prop | Type | Default | Description |
|---|---|---|---|
format | (value: number) => string | Formats as $ 0.00 | Worklet function that formats the numeric value |
style | TextStyle | {} | Style object for the inner text element |
containerStyle | ViewStyle | {} | Style object for the tooltip wrapper |
Chart.Tooltip.Date
| Prop | Type | Default | Description |
|---|---|---|---|
format | (timestamp: number) => string | Formats as DD/MM/YYYY | Worklet function that formats the timestamp |
style | TextStyle | {} | Style object for the inner text element |
containerStyle | ViewStyle | {} | Style object for the tooltip wrapper |
Related Resources
- @shopify/react-native-skia: Wraps the Skia graphics engine for React Native with a declarative API.
- react-native-reanimated: Runs animations and gesture callbacks on the UI thread using worklets.
- react-native-gesture-handler: Replaces the default gesture system with native-driven touch handling.
- Victory Native: A Charting library for React Native with SVG rendering and broad chart type support.
FAQs
Q: Why does the build fail with “missing libsvg.a” or a Skia crash?
A: Clean your Android build folder with cd android && ./gradlew clean, delete node_modules, and reinstall dependencies. Confirm that your @shopify/react-native-skia version matches your React Native version.
Q: Why do I see “Reanimated failed to create a worklet”?
A: Add 'react-native-reanimated/plugin' to your babel.config.js plugins array. Restart Metro with cache clearing by running npx react-native start --reset-cache.
Q: Can I use this library with Expo Go?
A: Expo Go cannot load custom native modules. Create a development build with npx expo run:android or npx expo run:ios to compile Skia and Reanimated.
Q: How do I change the tooltip position?
A: Apply margin or padding values to the containerStyle prop on Chart.Tooltip.Value or Chart.Tooltip.Date. The tooltip follows the cursor horizontally by default.
Q: Does the library support candlestick or bar charts?
A: The current release renders line and area charts only.