Skip to main content

Getting Started

Installation

Start by installing the peer dependencies of victory-nativeReact Native Reanimated, Gesture Handler, and Skia:

yarn add react-native-reanimated react-native-gesture-handler @shopify/react-native-skia

For Reanimated, you'll need to add "react-native-reanimated/plugin" to your plugins list in your babel.config.js config file.

Then install victory-native:

yarn add victory-native

Now you should be ready to go.

Your first chart

Let's create a basic line chart on a Cartesian grid. Let's mock out a little bit of mock data for "high temperature" for each day in a month:

const DATA = Array.from({ length: 31 }, (_, i) => ({
day: i,
highTmp: 40 + 30 * Math.random(),
}));

Instantiate a chart

Now, we'll use the CartesianChart component and pass in our data, specifying which property we'll be using for our x (independent variable) and y (dependent variable) keys.

import { View } from "react-native";
import { CartesianChart } from "victory-native";

// ...

function MyChart() {
return (
<View style={{ height: 300 }}>
// 👇 start our chart
<CartesianChart data={DATA} xKey="day" yKeys={["highTmp"]} />
</View>
);
}

At this point, we're you'll just see a blank view, since we aren't rendering anything useful to our charting canvas.

Add a line to the chart

The CartesianChart uses a render function for its children prop. To render content inside of the Cartesian chart, you return Skia elements from the children render function. We'll use the Line component from victory-native to render a line path using our temperature data.

import { View } from "react-native";
import { CartesianChart, Line } from "victory-native";

function MyChart() {
return (
<View style={{ height: 300 }}>
<CartesianChart data={DATA} xKey="day" yKeys={["highTmp"]}>
{/* 👇 render function exposes various data, such as points. */}
{({ points }) => (
// 👇 and we'll use the Line component to render a line path.
<Line points={points.highTmp} color="red" strokeWidth={3} />
)}
</CartesianChart>
</View>
);
}

Now we've got a line path to represent our daily high temperature data!

Screenshot of the line chart generated from the code above

Add some axes

You might want some axes to make your line graph a bit easier to read and interpret. The CartesianChart offers out-of-the-box support for axes and grids to make it easy to get up and running with some axes. Let's add some now.

import { View } from "react-native";
import { CartesianChart, Line } from "victory-native";
// 👇 import a font file you'd like to use for tick labels
import inter from "../assets/inter-medium.ttf";

function MyChart() {
const font = useFont(inter, 12);

return (
<View style={{ height: 300 }}>
<CartesianChart
data={DATA}
xKey="day"
yKeys={["highTmp"]}
// 👇 pass the font, opting in to axes.
axisOptions={{ font }}
>
{({ points }) => (
<Line points={points.highTmp} color="red" strokeWidth={3} />
)}
</CartesianChart>
</View>
);
}

And now we've got some axes and grid lines!

Screenshot of the line chart generated from the code above

Adding a tooltip

You might also want to give your users a way to interact with the line chart you've created. Handling user gestures can be complex, especially in canvas-like drawing context. Victory Native helps streamline this for you. To build a basic tooltip, we'll do three things.

  • Create a ChartPressState instance using the useChartPressState hook from victory-native.
  • Pass our state variable into our <CartesianChart /> element.
  • Use the Reanimated shared values from the ChartPressState instance in a custom ToolTip component that we'll create to create our tooltip element.

We'll start by creating our ChartPressState instance and pass it to our chart element.

// ...
import { /*...*/ useChartPressState } from "victory-native";

function MyChart() {
// ...
// 👇 create our chart press state
const { state, isActive } = useChartPressState({ x: 0, y: { highTmp: 0 } });

return (
// ...
<CartesianChart
// ...
chartPressState={state} // 👈 and pass it to our chart.
>
{/* ... */}
</CartesianChart>
// ...
);
}

// ...

Then we'll create a ToolTip component that uses some Reanimaed SharedValues from our state variable.

import type { SharedValue } from "react-native-reanimated";
// ...

function ToolTip({ x, y }: { x: SharedValue<number>; y: SharedValue<number> }) {
return <Circle cx={x} cy={y} r={8} color="black" />;
}

And we'll conditionally show an instance of this component when the chart press is active:

// ...
import { /*...*/ useChartPressState } from "victory-native";

function MyChart() {
// ...
const { state, isActive } = useChartPressState({ x: 0, y: { highTmp: 0 } });

return (
// ...
<CartesianChart
// ...
chartPressState={state}
>
{
(/*...*/) => (
<>
{/* 👇 Conditionally show our tooltip and pass values. */}
{isActive ? (
<ToolTip x={state.x.position} y={state.y.highTmp.position} />
) : null}
</>
)
}
</CartesianChart>
// ...
);
}

// ...

With this in place, we have a rather simple tooltip UI:

Putting this all together, we have something like the following:

import * as React from "react";
import { View } from "react-native";
import { CartesianChart, Line, useChartPressState } from "victory-native";
import { Circle, useFont } from "@shopify/react-native-skia";
import type { SharedValue } from "react-native-reanimated";
import inter from "../../assets/inter-medium.ttf"; // Wherever your font actually lives

function MyChart() {
const font = useFont(inter, 12);
const { state, isActive } = useChartPressState({ x: 0, y: { highTmp: 0 } });

return (
<View style={{ height: 300 }}>
<CartesianChart
data={DATA}
xKey="day"
yKeys={["highTmp"]}
axisOptions={{
font,
}}
chartPressState={state}
>
{({ points }) => (
<>
<Line points={points.highTmp} color="red" strokeWidth={3} />
{isActive && (
<ToolTip x={state.x.position} y={state.y.highTmp.position} />
)}
</>
)}
</CartesianChart>
</View>
);
}

function ToolTip({ x, y }: { x: SharedValue<number>; y: SharedValue<number> }) {
return <Circle cx={x} cy={y} r={8} color="black" />;
}

const DATA = Array.from({ length: 31 }, (_, i) => ({
day: i,
highTmp: 40 + 30 * Math.random(),
}));