React Native Financial Charts with Skia and Reanimated

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, and Chart.Cursor components 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 d3

If 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

PropTypeDefaultDescription
data{ timestamp: number, value: number }[]RequiredArray of data points with Unix timestamps in milliseconds
heightnumber250Total height of the chart in pixels
widthnumberScreen widthTotal width of the chart in pixels
paddingnumber20Horizontal padding inside the chart boundaries
containerStyleViewStyle{}Style object applied to the outer container view

Chart.Canvas

PropTypeDefaultDescription
childrenReact.ReactNodeNoneSkia-compatible child components only

Chart.Line

PropTypeDefaultDescription
strokeWidthnumber3Thickness of the line in pixels
colorsstring[]['#00E396', '#00E396', '#EA3943', '#EA3943']Gradient color stops from top to bottom

Chart.Area

PropTypeDefaultDescription
gradientColorsstring[]['#000', '#000', '#000', '#000']Four color stops for the area gradient

Chart.Cursor

PropTypeDefaultDescription
crosshairColorstring'white'Color of the vertical crosshair line
circleColorstring'white'Border color of the cursor circle indicator

Chart.Baseline

PropTypeDefaultDescription
colorstring'#858CA2'Color of the dashed baseline and starting dot
showLabelbooleantrueToggles visibility of the formatted value chip

Chart.Tooltip.Value

PropTypeDefaultDescription
format(value: number) => stringFormats as $ 0.00Worklet function that formats the numeric value
styleTextStyle{}Style object for the inner text element
containerStyleViewStyle{}Style object for the tooltip wrapper

Chart.Tooltip.Date

PropTypeDefaultDescription
format(timestamp: number) => stringFormats as DD/MM/YYYYWorklet function that formats the timestamp
styleTextStyle{}Style object for the inner text element
containerStyleViewStyle{}Style object for the tooltip wrapper

Related Resources

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.

Add Comment