DEV Community

Eric Lewis
Eric Lewis

Posted on

Building Interactive Charts with Victory

Victory is a powerful charting library for React that provides a comprehensive set of composable components for creating beautiful, animated, and interactive data visualizations. It offers extensive customization options and built-in animations, making it ideal for creating professional dashboards and analytics visualizations. This guide walks through setting up and creating charts using Victory with React, from installation to a working implementation.

Prerequisites

Before you begin, make sure you have:

  • Node.js version 14.0 or higher installed
  • npm, yarn, or pnpm package manager
  • A React project (version 16.8 or higher) or create-react-app setup
  • Basic knowledge of React hooks (useState)
  • Familiarity with JavaScript/TypeScript
  • Understanding of data visualization concepts

Installation

Install Victory using your preferred package manager:

npm install victory
Enter fullscreen mode Exit fullscreen mode

Or with yarn:

yarn add victory
Enter fullscreen mode Exit fullscreen mode

Or with pnpm:

pnpm add victory
Enter fullscreen mode Exit fullscreen mode

After installation, your package.json should include:

{
  "dependencies": {
    "victory": "^36.0.0",
    "react": "^18.0.0",
    "react-dom": "^18.0.0"
  }
}
Enter fullscreen mode Exit fullscreen mode

Project Setup

Victory requires minimal setup. Import the components and you're ready to use them.

First Example / Basic Usage

Let's create a simple line chart. Create a new file src/ChartExample.jsx:

// src/ChartExample.jsx
import React from 'react';
import {
  VictoryChart,
  VictoryLine,
  VictoryAxis,
  VictoryTheme
} from 'victory';

function ChartExample() {
  const data = [
    { x: 'Jan', y: 35 },
    { x: 'Feb', y: 28 },
    { x: 'Mar', y: 34 },
    { x: 'Apr', y: 32 },
    { x: 'May', y: 40 },
    { x: 'Jun', y: 32 }
  ];

  return (
    <div style={{ padding: '20px', maxWidth: '800px', margin: '0 auto' }}>
      <h2>Basic Victory Example</h2>
      <VictoryChart theme={VictoryTheme.material}>
        <VictoryAxis />
        <VictoryAxis dependentAxis />
        <VictoryLine data={data} />
      </VictoryChart>
    </div>
  );
}

export default ChartExample;
Enter fullscreen mode Exit fullscreen mode

Update your App.jsx:

// src/App.jsx
import React from 'react';
import ChartExample from './ChartExample';
import './App.css';

function App() {
  return (
    <div className="App">
      <ChartExample />
    </div>
  );
}

export default App;
Enter fullscreen mode Exit fullscreen mode

This creates a basic line chart with animated transitions.

Understanding the Basics

Victory provides composable chart components:

  • VictoryChart: Main chart container
  • VictoryLine, VictoryBar, VictoryArea: Data series components
  • VictoryAxis: Axis components
  • VictoryTheme: Pre-built themes
  • VictoryTooltip: Interactive tooltips
  • VictoryLegend: Chart legends

Key concepts:

  • Composable API: Build charts by composing components
  • Data format: Array of objects with x and y properties
  • Themes: Use pre-built themes or create custom ones
  • Animations: Built-in animations for all components
  • Interactive: Built-in tooltips and event handling

Here's an example with multiple chart types:

// src/MultipleChartsExample.jsx
import React from 'react';
import {
  VictoryChart,
  VictoryLine,
  VictoryBar,
  VictoryArea,
  VictoryAxis,
  VictoryTheme
} from 'victory';

function MultipleChartsExample() {
  const lineData = [
    { x: 'Mon', y: 120 },
    { x: 'Tue', y: 132 },
    { x: 'Wed', y: 101 },
    { x: 'Thu', y: 134 },
    { x: 'Fri', y: 90 }
  ];

  const barData = [
    { x: 'Product A', y: 120 },
    { x: 'Product B', y: 200 },
    { x: 'Product C', y: 150 }
  ];

  return (
    <div style={{ padding: '20px', maxWidth: '1200px', margin: '0 auto' }}>
      <h2>Multiple Charts Example</h2>
      <div style={{ display: 'flex', flexDirection: 'column', gap: '40px' }}>
        <div>
          <h3>Line Chart</h3>
          <VictoryChart theme={VictoryTheme.material}>
            <VictoryAxis />
            <VictoryAxis dependentAxis />
            <VictoryLine data={lineData} />
          </VictoryChart>
        </div>
        <div>
          <h3>Bar Chart</h3>
          <VictoryChart theme={VictoryTheme.material}>
            <VictoryAxis />
            <VictoryAxis dependentAxis />
            <VictoryBar data={barData} />
          </VictoryChart>
        </div>
        <div>
          <h3>Area Chart</h3>
          <VictoryChart theme={VictoryTheme.material}>
            <VictoryAxis />
            <VictoryAxis dependentAxis />
            <VictoryArea data={lineData} />
          </VictoryChart>
        </div>
      </div>
    </div>
  );
}

export default MultipleChartsExample;
Enter fullscreen mode Exit fullscreen mode

Practical Example / Building Something Real

Let's build a comprehensive dashboard with multiple charts:

// src/DashboardCharts.jsx
import React, { useState } from 'react';
import {
  VictoryChart,
  VictoryLine,
  VictoryBar,
  VictoryPie,
  VictoryAxis,
  VictoryTheme,
  VictoryTooltip,
  VictoryLegend
} from 'victory';

function DashboardCharts() {
  const [selectedPeriod, setSelectedPeriod] = useState('monthly');

  const monthlyData = [
    { x: 'Jan', y: 35 },
    { x: 'Feb', y: 28 },
    { x: 'Mar', y: 34 },
    { x: 'Apr', y: 32 },
    { x: 'May', y: 40 },
    { x: 'Jun', y: 32 }
  ];

  const quarterlyData = [
    { x: 'Q1', y: 97 },
    { x: 'Q2', y: 106 },
    { x: 'Q3', y: 112 },
    { x: 'Q4', y: 120 }
  ];

  const revenueData = [
    { x: 'Q1', y: 12000 },
    { x: 'Q2', y: 15000 },
    { x: 'Q3', y: 18000 },
    { x: 'Q4', y: 20000 }
  ];

  const categoryData = [
    { x: 'Product A', y: 35 },
    { x: 'Product B', y: 28 },
    { x: 'Product C', y: 34 },
    { x: 'Product D', y: 32 }
  ];

  const currentData = selectedPeriod === 'monthly' ? monthlyData : quarterlyData;

  return (
    <div style={{ padding: '20px', maxWidth: '1200px', margin: '0 auto' }}>
      <h1>Analytics Dashboard</h1>
      <div style={{ marginBottom: '20px', textAlign: 'center' }}>
        <button
          onClick={() => setSelectedPeriod('monthly')}
          style={{
            padding: '8px 16px',
            margin: '0 5px',
            backgroundColor: selectedPeriod === 'monthly' ? '#007bff' : '#6c757d',
            color: 'white',
            border: 'none',
            borderRadius: '4px',
            cursor: 'pointer'
          }}
        >
          Monthly
        </button>
        <button
          onClick={() => setSelectedPeriod('quarterly')}
          style={{
            padding: '8px 16px',
            margin: '0 5px',
            backgroundColor: selectedPeriod === 'quarterly' ? '#007bff' : '#6c757d',
            color: 'white',
            border: 'none',
            borderRadius: '4px',
            cursor: 'pointer'
          }}
        >
          Quarterly
        </button>
      </div>
      <div style={{ display: 'flex', flexDirection: 'column', gap: '40px' }}>
        <div>
          <h2>Sales Performance</h2>
          <VictoryChart theme={VictoryTheme.material}>
            <VictoryAxis />
            <VictoryAxis dependentAxis />
            <VictoryLine
              data={currentData}
              style={{
                data: { stroke: '#c43a31', strokeWidth: 2 }
              }}
            />
            <VictoryTooltip />
          </VictoryChart>
        </div>
        <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '20px' }}>
          <div>
            <h2>Quarterly Revenue</h2>
            <VictoryChart theme={VictoryTheme.material}>
              <VictoryAxis />
              <VictoryAxis dependentAxis />
              <VictoryBar
                data={revenueData}
                style={{
                  data: { fill: '#c43a31' }
                }}
              />
              <VictoryTooltip />
            </VictoryChart>
          </div>
          <div>
            <h2>Product Distribution</h2>
            <VictoryPie
              data={categoryData}
              colorScale={['#c43a31', '#f39c12', '#3498db', '#2ecc71']}
              labelRadius={({ innerRadius }) => innerRadius + 20}
              style={{
                labels: { fill: 'white', fontSize: 12, fontWeight: 'bold' }
              }}
            />
          </div>
        </div>
      </div>
    </div>
  );
}

export default DashboardCharts;
Enter fullscreen mode Exit fullscreen mode

Now create an interactive chart with custom styling:

// src/InteractiveChart.jsx
import React, { useState } from 'react';
import {
  VictoryChart,
  VictoryLine,
  VictoryAxis,
  VictoryTheme,
  VictoryTooltip,
  VictoryVoronoiContainer
} from 'victory';

function InteractiveChart() {
  const [selectedPoint, setSelectedPoint] = useState(null);

  const data = [
    { x: 'Jan', y: 35 },
    { x: 'Feb', y: 28 },
    { x: 'Mar', y: 34 },
    { x: 'Apr', y: 32 },
    { x: 'May', y: 40 },
    { x: 'Jun', y: 32 }
  ];

  return (
    <div style={{ padding: '20px', maxWidth: '900px', margin: '0 auto' }}>
      <h2>Interactive Chart</h2>
      {selectedPoint && (
        <div style={{
          padding: '10px',
          backgroundColor: '#f8f9fa',
          borderRadius: '4px',
          marginBottom: '20px'
        }}>
          Selected: {selectedPoint.x} - {selectedPoint.y}
        </div>
      )}
      <VictoryChart
        theme={VictoryTheme.material}
        containerComponent={<VictoryVoronoiContainer />}
        onActivated={(points) => {
          if (points.length > 0) {
            setSelectedPoint(points[0]);
          }
        }}
      >
        <VictoryAxis />
        <VictoryAxis dependentAxis />
        <VictoryLine
          data={data}
          style={{
            data: { stroke: '#c43a31', strokeWidth: 2 }
          }}
        />
        <VictoryTooltip />
      </VictoryChart>
    </div>
  );
}

export default InteractiveChart;
Enter fullscreen mode Exit fullscreen mode

Update your App.jsx:

// src/App.jsx
import React from 'react';
import DashboardCharts from './DashboardCharts';
import InteractiveChart from './InteractiveChart';
import './App.css';

function App() {
  return (
    <div className="App">
      <DashboardCharts />
      <InteractiveChart />
    </div>
  );
}

export default App;
Enter fullscreen mode Exit fullscreen mode

This example demonstrates:

  • Multiple chart types
  • Dashboard layout
  • Interactive features
  • Custom styling
  • Dynamic data updates
  • Tooltips and legends

Common Issues / Troubleshooting

  1. Chart not displaying: Make sure you're importing components correctly from 'victory'. Check that the data array is properly formatted.

  2. Data format error: Ensure data is an array of objects with x and y properties. Both should be present in each object.

  3. Styling issues: Customize colors through the style prop. Use data property for series styling and labels for text styling.

  4. Axis not showing: Add VictoryAxis components inside VictoryChart. Use dependentAxis prop for Y-axis.

  5. Animations not working: Animations are enabled by default. Disable them with animate={false} if needed.

  6. Performance: For large datasets, consider data sampling or using VictoryZoomContainer for zooming. Victory handles large datasets well, but optimization may be needed for very large datasets.

Next Steps

Now that you have an understanding of Victory:

  • Explore all available chart types
  • Learn about advanced configurations
  • Implement custom themes
  • Add animations and transitions
  • Create real-time updating charts
  • Learn about other chart libraries
  • Check the official repository: https://github.com/FormidableLabs/victory

Summary

You've successfully set up Victory in your React application and created line charts, bar charts, pie charts, and interactive visualizations. Victory provides a powerful, composable solution for creating animated data visualizations with extensive customization options.

SEO Keywords

victory
React Victory
victory tutorial
React data visualization
victory installation
React chart library
victory example
React animated charts
victory setup
React interactive charts
victory customization
React chart component
victory dashboard
React visualization library
victory getting started

Top comments (0)