README.md

September 17, 2026 ยท View on GitHub

Nitro Modules

๐Ÿ“ˆ
react-native-graph

Beautiful, high-performance Graphs/Charts for React Native.

About

react-native-graph is a Line Graph implementation based on the high performance 2D graphics rendering engine "Skia". It's used in the Bamboo app to power thousands of token graphs every day.

  • ๐ŸŽ๏ธ Faster and smoother than react-native-svg graphs
  • โšก๏ธ Native path interpolation in Skia
  • ๐ŸŽ Up to 120 FPS animations
  • ๐Ÿ“ˆ Cubic bezier rendering for smoother edges
  • ๐Ÿ‘ Smooth pan/scrubbing gesture
  • ๐Ÿ’ฐ Made for crypto apps and Wallets
  • โŒ Does not block navigation, press or scroll animations

Installation

yarn add react-native-reanimated # Reanimated requires react-native-worklets
yarn add react-native-gesture-handler
yarn add @shopify/react-native-skia
yarn add react-native-graph

Expo

The Expo example runs in Expo Go with Expo SDK 57. Install react-native-graph alongside the Expo SDK's compatible versions of Skia, Reanimated, Worklets, and Gesture Handler. Start the example from its example directory and open it in Expo Go to try the graph without building a custom development client.

Usage

import { LineGraph, type GraphPoint } from 'react-native-graph';

const priceHistory: GraphPoint[] = [
  { date: new Date('2026-08-27T00:00:00Z'), value: 3.44 },
  { date: new Date('2026-08-28T00:00:00Z'), value: 3.51 },
  { date: new Date('2026-08-29T00:00:00Z'), value: 3.49 },
];

function App() {
  return (
    <LineGraph
      style={{ height: 200 }}
      points={priceHistory}
      animated={false}
      color="#4484B2"
    />
  );
}

react-native-graph does not fetch data or provide a usePriceHistory hook. Create the GraphPoint[] from your own API, state, or local data. Each point uses a Date for its horizontal position and a number for its vertical value; keep the points ordered from oldest to newest. Categorical string values are not supported on the x-axis.

Configuration

LineGraph accepts the following props. It also accepts React Native ViewProps, which are forwarded to the root view.

PropTypeDefaultAvailabilityDescription
animatedbooleanfalseAlwaysUses the animated renderer when true and the lightweight static renderer when false.
pointsGraphPoint[]None. Required.AlwaysThe points to draw. Each point contains a numeric value and a Date. The graph scales to fit them unless range overrides an axis.
colorstringNone. Required.AlwaysThe graph line color.
rangeGraphRangeundefined. Both axes are inferred from points.AlwaysOverrides all or part of the visible x-axis and y-axis ranges.
gradientFillColorsColor[]undefined. No area fill is drawn.animated={true}Colors for the vertical gradient below the graph line.
lineThicknessnumber3AlwaysThe graph line width in points.
enableFadeInMaskbooleanfalseAlwaysFades in the start of the graph line.
enablePanGesturebooleanfalseanimated={true}Lets the user press and scrub through graph points.
panGestureDelaynumber300animated={true}Time in milliseconds that a press must be held before scrubbing starts. Set it to 0 to start immediately.
onGestureStart() => voidundefined. No callback runs.animated={true}Called when scrubbing starts.
onPointSelected(point: GraphPoint) => voidundefined. No callback runs.animated={true}Called when scrubbing reaches a different point.
onGestureEnd() => voidundefined. No callback runs.animated={true}Called when scrubbing ends.
SelectionDotComponentType<SelectionDotProps> | nullBuilt-in SelectionDotanimated={true}Renders the current scrub position. Pass null to hide it.
selectionDotShadowColorstringundefinedanimated={true}Currently unused. This prop has no visual effect.
horizontalPaddingnumber10 when the indicator is enabled, otherwise 0animated={true}Adds space to both horizontal edges of the drawing area.
verticalPaddingnumberThe value of lineThicknessanimated={true}Adds space to both vertical edges of the drawing area.
enableIndicatorbooleanfalseanimated={true}Shows an indicator at the last graph point.
indicatorPulsatingbooleanfalseanimated={true}Pulses the indicator while the graph is idle. Requires enableIndicator.
TopAxisLabel() => ReactElement | nullundefined. Nothing is rendered.animated={true}Renders a label above the graph.
BottomAxisLabel() => ReactElement | nullundefined. Nothing is rendered.animated={true}Renders a label below the graph.

Data types

interface GraphPoint {
  value: number;
  date: Date;
}

interface GraphRange {
  x?: { min: Date; max: Date };
  y?: { min: number; max: number };
}

You can provide either axis in range and let the graph infer the other one from points.

Prop examples

animated

Whether to animate between data changes. Defaults to false when omitted.

Animations run using the Skia animation system, with path interpolation handled on the UI thread.

If animated is false, the graph uses a lightweight static renderer. This is useful when displaying many graphs in a list.

Example:

<LineGraph points={priceHistory} animated={true} color="#4484B2" />

enablePanGesture

Whether to enable the pan gesture. Defaults to false.

Requires animated to be true.

There are three events fired when the user interacts with the graph:

  1. onGestureStart: Fires once the user presses and holds the graph. The pan gesture activates.
  2. onPointSelected: Fires for each point the user pans through. Use it to update a label or highlight the selected value.
  3. onGestureEnd: Fires once the user releases the graph. The pan gesture deactivates.

The pan gesture can be configured using these props:

  • panGestureDelay controls how long the user must hold before the gesture activates. It defaults to 300 milliseconds. Set it to 0 to start immediately.

Example:

<LineGraph
  points={priceHistory}
  animated={true}
  color="#4484B2"
  enablePanGesture={true}
  onGestureStart={() => hapticFeedback('impactLight')}
  onPointSelected={(p) => updatePriceTitle(p)}
  onGestureEnd={() => resetPriceTitle()}
/>

TopAxisLabel / BottomAxisLabel

Renders labels above or below the graph. Both props default to undefined, so no labels are rendered.

Requires animated to be true.

These labels usually show the maximum and minimum values. AxisLabel is not a component exported by this package: both props are callbacks that receive no arguments and render any React Native element you provide. The graph reserves a row above or below the canvas; positioning and styling inside that row belong to your label component.

Example:

import { Text } from 'react-native';

function PriceGraph() {
  const values = priceHistory.map((point) => point.value);
  const maxValue = Math.max(...values);
  const minValue = Math.min(...values);

  return (
    <LineGraph
      points={priceHistory}
      animated={true}
      color="#4484B2"
      TopAxisLabel={() => <Text>{`Max: ${maxValue.toFixed(2)}`}</Text>}
      BottomAxisLabel={() => <Text>{`Min: ${minValue.toFixed(2)}`}</Text>}
    />
  );
}

range

Defines the visible range of the graph canvas. It defaults to undefined, which infers both axes from points.

Use a custom range to show a fixed time frame or value scale, even when the data does not cover the whole range. Points outside the x-axis range are not drawn.



This example shows January 2000 and sets the y-axis range to 0 through 200:

<LineGraph
  points={priceHistory}
  animated={true}
  color="#4484B2"
  enablePanGesture={true}
  range={{
    x: {
      min: new Date('2000-01-01T00:00:00.000Z'),
      max: new Date('2000-01-31T23:59:59.999Z'),
    },
    y: {
      min: 0,
      max: 200,
    },
  }}
/>

SelectionDot

Renders the selection dot. It defaults to the built-in SelectionDot. Pass null to hide it.

Requires animated and enablePanGesture to be true.

A custom selection-dot component receives these props from LineGraph. They are all required and have no defaults when you render SelectionDot directly.

PropTypeDefaultDescription
isActiveSharedValue<boolean>None. Required.Whether the pan gesture is active.
colorstringNone. Required.The graph line color.
lineThicknessnumber | undefinedNone. Required.The resolved graph line width when supplied by LineGraph.
circleXSharedValue<number>None. Required.The selected point's x-coordinate.
circleYSharedValue<number>None. Required.The selected point's y-coordinate.

Example:

<LineGraph
  points={priceHistory}
  animated={true}
  color="#4484B2"
  enablePanGesture={true}
  SelectionDot={CustomSelectionDot}
/>

See this example <SelectionDot /> component.

react-native-graph is sponsored by Pink Panda.

Download the Pink Panda mobile app to see react-native-graph in action!

Community Discord

Join the Margelo Community Discord to chat about react-native-graph or other Margelo libraries.

Adopting at scale

react-native-graph was built at Margelo, an elite app development agency. For enterprise support or other business inquiries, contact us at hello@margelo.com!

Thanks

Special thanks to William Candillon and Christian Falch for their amazing help and support for React Native Skia โค๏ธ