Categories
React

Add Charts into Our React App with Victory — Plot Functions and Events

The Victory lets us add charts and data visualization into our React app.

In this article, we’ll look at how to add charts into our React app with Victory.

Plot Functions

We can plot functions in our React app with Victory easily.

For example, we can write:

import React from "react";
import { VictoryChart, VictoryLine } from "victory";

export default function App() {
  return (
    <VictoryChart>
      <VictoryLine
        samples={50}
        style={{ data: { stroke: "red", strokeWidth: 4 } }}
        y={(data) => Math.sin(2 * Math.PI * data.x)}
      />
    </VictoryChart>
  );
}

We set the samples prop to set the number of points to plot.

Then y is set to a function with the values we want to plot.

We get the x-axis value with data.x and do what we want with it.

Component Events

We can add event handlers for components in our charts.

For example, we can write:

import React from "react";
import { VictoryBar } from "victory";

export default function App() {
  return (
    <VictoryBar
      data={[
        { x: 1, y: 2, label: "A" },
        { x: 2, y: 4, label: "B" },
        { x: 3, y: 7, label: "C" },
        { x: 4, y: 3, label: "D" },
        { x: 5, y: 5, label: "E" }
      ]}
      events={[
        {
          target: "data",
          eventHandlers: {
            onClick: () => {
              return [
                {
                  target: "labels",
                  mutation: (props) => {
                    return props.text === "clicked"
                      ? null
                      : { text: "clicked" };
                  }
                }
              ];
            }
          }
        }
      ]}
    />
  );
}

to add the events prop into our VictoryBar component.

In it, we add the eventHandlers.onClick function to add click handlers to each bar.

Then in the mutation method, we toggle the ‘clicked’ text as we click the bars.

Nested Component Events

We can trigger change in one part of the chart from other parts of the chart.

For instance, we can write:

import React from "react";
import { VictoryArea, VictoryBar, VictoryChart, VictoryStack } from "victory";

export default function App() {
  return (
    <VictoryChart
      events={[
        {
          childName: ["area-1", "area-2"],
          target: "data",
          eventHandlers: {
            onClick: () => {
              return [
                {
                  childName: "area-4",
                  mutation: (props) => {
                    const fill = props.style.fill;
                    return fill === "green"
                      ? null
                      : { style: { fill: "green" } };
                  }
                }
              ];
            }
          }
        }
      ]}
    >
      <VictoryStack>
        <VictoryArea
          name="area-1"
          data={[
            { x: "a", y: 2 },
            { x: "b", y: 3 },
            { x: "c", y: 5 },
            { x: "d", y: 4 }
          ]}
        />
        <VictoryArea
          name="area-2"
          data={[
            { x: "a", y: 1 },
            { x: "b", y: 4 },
            { x: "c", y: 5 },
            { x: "d", y: 7 }
          ]}
        />
        <VictoryArea
          name="area-3"
          data={[
            { x: "a", y: 3 },
            { x: "b", y: 2 },
            { x: "c", y: 6 },
            { x: "d", y: 2 }
          ]}
        />
        <VictoryArea
          name="area-4"
          data={[
            { x: "a", y: 2 },
            { x: "b", y: 3 },
            { x: "c", y: 3 },
            { x: "d", y: 4 }
          ]}
        />
      </VictoryStack>
    </VictoryChart>
  );
}

We have 4 VictoryArea components to display filled areas formed from the points.

Then we add the events prop to VictoryChart .

childName has the name values of the components that triggers the mutation function.

Then in the onClick method we return an array with objects that specifies which component changes and how they change.

childName has the name of the component that changes.

mutation has the code to change the component specified in childName in the array returned by onClick .

We toggle the fill between 'green' and null on the VictoryArea with name area-4 .

Conclusion

We can plot functions and listen for events in chart components in React Victory’s charts.

Categories
React

Add Charts into Our React App with Victory — Data Processing

The Victory lets us add charts and data visualization into our React app.

In this article, we’ll look at how to add charts into our React app with Victory.

Specifying x and y Data

We can specify the data for the x and y axes with the property name if we have an array of objects as data.

For instance, we can write:

import React from "react";
import { VictoryBar, VictoryChart } from "victory";

export default function App() {
  return (
    <VictoryChart domainPadding={50}>
      <VictoryBar
        data={[
          { employee: "Jane Doe", salary: 65000 },
          { employee: "John Doe", salary: 62000 }
        ]}
        x="employee"
        y="salary"
      />
    </VictoryChart>
  );
}

We set the x and y props to the property names with the data for the x and y axes respectively.

If we have an array of arrays, we can specify the index with the data we want to display for the x and y axes:

import React from "react";
import { VictoryBar, VictoryChart } from "victory";

export default function App() {
  return (
    <VictoryChart domainPadding={50}>
      <VictoryBar
        data={[
          [1, 1],
          [2, 3],
          [3, 1]
        ]}
        x={0}
        y={1}
      />
    </VictoryChart>
  );
}

If we have an array od nested objects, we can also specify the path string or an array of strings to form the property path with the data we want to display:

import React from "react";
import { VictoryBar, VictoryChart } from "victory";

export default function App() {
  return (
    <VictoryChart domainPadding={50}>
      <VictoryBar
        data={[
          {
            employee: { firstName: "Jane", lastName: "Doe" },
            salary: { base: 65000, bonus: 2000 }
          },
          {
            employee: { firstName: "John", lastName: "Doe" },
            salary: { base: 62000, bonus: 6000 }
          }
        ]}
        x="employee.firstName"
        y={["salary", "base"]}
      />
    </VictoryChart>
  );
}

Processing Data

We can process data by passing in functions for the x and y props:

import React from "react";
import { VictoryAxis, VictoryBar, VictoryChart } from "victory";

export default function App() {
  return (
    <VictoryChart domainPadding={{ x: 40 }}>
      <VictoryBar
        data={[
          { experiment: "trial 1", expected: 3.95, actual: 3.21 },
          { experiment: "trial 2", expected: 3.95, actual: 3.38 },
          { experiment: "trial 3", expected: 3.95, actual: 2.05 },
          { experiment: "trial 4", expected: 3.95, actual: 3.71 }
        ]}
        x="experiment"
        y={(d) => (d.actual / d.expected) * 100}
      />
      <VictoryAxis
        label="experiment"
        style={{
          axisLabel: { padding: 30 }
        }}
      />
      <VictoryAxis
        dependentAxis
        label="percent yield"
        style={{
          axisLabel: { padding: 40 }
        }}
      />
    </VictoryChart>
  );
}

We pass in a function to compute the value of y to display with a function.

d has the data entry we want to compute.

Sorting Data

We can sort our data with the sortKey prop:

import React from "react";
import { VictoryChart, VictoryLine } from "victory";
import { range } from "lodash";

export default function App() {
  return (
    <VictoryChart domainPadding={{ x: 40 }}>
      <VictoryLine
        data={range(0, 2 * Math.PI, 0.01).map((t) => ({ t }))}
        sortKey="t"
        x={({ t }) => Math.sin(3 * t + 2 * Math.PI)}
        y={({ t }) => Math.sin(2 * t)}
      />
    </VictoryChart>
  );
}

Since sortKey is set to t , we sort by the t value.

Conclusion

We can process our data in various ways to create the chart we want with React Victory.

Categories
React

Add Charts into Our React App with Victory — Custom Chart Components

The Victory lets us add charts and data visualization into our React app.

In this article, we’ll look at how to add charts into our React app with Victory.

Polygon Charts

We can add polygon charts with the Polygon component.

For instance, we can write:

import React from "react";
import { VictoryChart, VictoryScatter } from "victory";

const data = [
  { x: 2, y: 1 },
  { x: 3, y: 5 },
  { x: 6, y: 3 }
];

const Polygon = (props) => {
  const getPoints = (data, scale) => {
    return data.reduce(
      (pointStr, { x, y }) => `${pointStr} ${scale.x(x)},${scale.y(y)}`,
      ""
    );
  };

  const { data, style, scale } = props;
  const points = getPoints(data, scale);
  return <polygon points={points} style={style} />;
};

export default function App() {
  return (
    <VictoryChart height={400} width={400} domain={[-10, 10]}>
      <Polygon data={data} style={{ fill: "tomato", opacity: 0.5 }} />
      <VictoryScatter data={data} />
    </VictoryChart>
  );
}

We create the getPoint function in the Polygon component to create the point string for the polygon path.

Then we pass that into the polygon element to create the points.

In App , we pass in the Polygon component with the data prop to create the polygon from the given corner points.

We render the same points as dots with the VictoryScatter component.

Using Victory Components to Create Custom Components

We can use Victory components to create custom components.

For instance, we can write:

import React from "react";
import {
  VictoryAxis,
  VictoryChart,
  VictoryGroup,
  VictoryLine,
  VictoryPie,
  VictoryScatter
} from "victory";

const data = [
  { x: 2, y: 1 },
  { x: 3, y: 5 },
  { x: 6, y: 3 }
];

const CustomPie = (props) => {
  const { datum, x, y } = props;
  const pieWidth = 120;

  return (
    <g transform={`translate(${x - pieWidth / 2}, ${y - pieWidth / 2})`}>
      <VictoryPie
        standalone={false}
        height={pieWidth}
        width={pieWidth}
        data={datum.pie}
        style={{ labels: { fontSize: 0 } }}
        colorScale={["#f77", "#55e", "#8af"]}
      />
    </g>
  );
};

export default function App() {
  return (
    <VictoryChart domain={{ y: [0, 100] }}>
      <VictoryAxis />
      <VictoryGroup data={data}>
        <VictoryLine />
        <VictoryScatter dataComponent={<CustomPie />} />
      </VictoryGroup>
    </VictoryChart>
  );
}

We create the CustomPie component that renders small pie charts with the VictoryPie component to render pie charts as points.

The in App , we render VictoryGroup to render the data by setting it as the data prop.

VictoryScatter lets us render the points.

And we set CustomPie as the dataComponent prop to render the pies as points.

We can pass in any SVG component as point components in the dataComponent prop.

For instance, we can use styled-components to create the SVG circles for the points:

import React from "react";
import styled from "styled-components";
import { VictoryChart, VictoryLine, VictoryScatter } from "victory";

const data = [
  { x: 2, y: 1 },
  { x: 3, y: 5 },
  { x: 6, y: 3 }
];

const StyledPoint = styled.circle`
  fill: ${(props) => props.color};
`;

const colors = ["#A8E6CE", "#DCEDC2", "#FFD3B5", "#FFAAA6", "#FF8C94"];

const ScatterPoint = ({ x, y, datum, min, max }) => {
  const i = React.useMemo(() => {
    return Math.floor(((datum.y - min) / (max - min)) * (colors.length - 1));
  }, [datum, min, max]);

return <StyledPoint color={colors[i]} cx={x} cy={y} r={6} />;
};

export default function App() {
  const temperatures = data.map(({ y }) => y);
  const min = Math.min(...temperatures);
  const max = Math.max(...temperatures);

  return (
    <VictoryChart>
      <VictoryLine data={data} />
      <VictoryScatter
        data={data}
        dataComponent={<ScatterPoint min={min} max={max} />}
      />
    </VictoryChart>
  );
}

The StyledPoint component has the points.

And ScatterPoint renders the StyledPoint with the fill color for the point.

Then we pass the ScatterPoint as the value of dataComponent to render the points.

Conclusion

We can render polygon charts and create custom components for charts with React Victory.

Categories
React

Add Charts into Our React App with Victory — Custom Labels and Points

The Victory lets us add charts and data visualization into our React app.

In this article, we’ll look at how to add charts into our React app with Victory.

Altering Default Label Components

We can override the appearance of the components that comes with Victory.

For instance, we can change the labels that are displayed with bar charts by writing:

import React from "react";
import { VictoryBar, VictoryLabel } from "victory";

export default function App() {
  return (
    <VictoryBar
      data={[
        { x: 1, y: 3, label: "Alpha" },
        { x: 2, y: 4, label: "Bravo" },
        { x: 3, y: 6, label: "Charlie" },
        { x: 4, y: 3, label: "Delta" },
        { x: 5, y: 7, label: "Echo" }
      ]}
      labelComponent={
        <VictoryLabel angle={90} verticalAnchor="middle" textAnchor="end" />
      }
    />
  );
}

We set the angle of the VictoryLabel to display the labels vertically.

textAnchor is set to end to move them to the right.

Wrapping Components

We can wrap components to display what we want.

For instance, we can create our own wrapper component to add labels to our chart:

import React from "react";
import { VictoryChart, VictoryLabel, VictoryScatter } from "victory";

const WrapperComponent = (props) => {
  const renderChildren = () => {
    const children = React.Children.toArray(props.children);
    return children.map((child) => {
      const style = { ...child.props.style, ...props.style };
      return React.cloneElement(
        child,
        Object.assign({}, child.props, props, { style })
      );
    });
  };

  return (
    <g transform="translate(20, 40)">
      <VictoryLabel text={"add labels"} x={110} y={30} />
      <VictoryLabel text={"offset data from axes"} x={70} y={150} />
      <VictoryLabel text={"alter props"} x={280} y={150} />
      {renderChildren()}
    </g>
  );
};

export default function App() {
  return (
    <VictoryChart>
      <WrapperComponent>
        <VictoryScatter
          y={(d) => Math.sin(2 * Math.PI * d.x)}
          samples={15}
          symbol="square"
          size={6}
          style={{ data: { stroke: "tomato", strokeWidth: 3 } }}
        />
      </WrapperComponent>
    </VictoryChart>
  );
}

WrapperComponent takes the child components from the children prop and render them with React.cloneElement .

We also combine the styles by merging the styles from the child and the props.

In the return statement, we have the VictoryLabel s and call the renderChildren function to render the child items.

Then in App , we render VictoryScatter in the WrapperComponent to render the sine curve with the VictoryLabel s.

Customize Points

For instance, we can create the CatPoint component and pass that as the value of dataComponent in the VictoryScatter component:

import React from "react";
import { VictoryChart, VictoryScatter } from "victory";

const CatPoint = (props) => {
  const { x, y, datum } = props;
  const cat = datum._y >= 0 ? "?" : "?";
  return (
    <text x={x} y={y} fontSize={30}>
      {cat}
    </text>
  );
};

export default function App() {
  return (
    <VictoryChart>
      <VictoryScatter
        y={(d) => Math.sin(2 * Math.PI * d.x)}
        samples={25}
        dataComponent={<CatPoint />}
      />
    </VictoryChart>
  );
}

We get the data entry from the datum prop, and the _y property has the y value.

x and y has the position.

Conclusion

We can customize labels and points with charts created with Victory in our React app.

Categories
React

Add Charts into Our React App with Victory — Custom Chart

The Victory lets us add charts and data visualization into our React app.

In this article, we’ll look at how to add charts into our React app with Victory.

Custom Chart

We can create a custom chart by adding multiple components together.

For instance, we can write:

import React from "react";
import { VictoryAxis, VictoryLabel, VictoryLine } from "victory";

const getDataSetOne = () => {
  return [
    { x: new Date(2000, 1, 1), y: 12 },
    { x: new Date(2001, 6, 1), y: 10 },
    { x: new Date(2002, 12, 1), y: 11 },
    { x: new Date(2003, 1, 1), y: 5 },
    { x: new Date(2004, 1, 1), y: 4 }
  ];
};

const getDataSetTwo = () => {
  return [
    { x: new Date(2000, 1, 1), y: 5 },
    { x: new Date(2001, 1, 1), y: 6 },
    { x: new Date(2002, 1, 1), y: 4 },
    { x: new Date(2003, 1, 1), y: 10 },
    { x: new Date(2004, 1, 1), y: 12 }
  ];
};

const getTickValues = () => {
  return [
    new Date(2000, 1, 1),
    new Date(2001, 1, 1),
    new Date(2002, 1, 1),
    new Date(2003, 1, 1),
    new Date(2004, 1, 1)
  ];
};

const dataSetOne = getDataSetOne();
const dataSetTwo = getDataSetTwo();
const tickValues = getTickValues();

export default function App() {
  return (
    <svg viewBox="0 0 450 350">
      <VictoryLabel
        x={25}
        y={55}
        text={"Economy n % change on a year earlier"}
      />
      <VictoryLabel x={200} y={55} text={"Dinosaur exportsn $bn"} />

<g transform={"translate(0, 40)"}>
        <VictoryAxis
          scale="time"
          standalone={false}
          tickValues={tickValues}
          tickFormat={(x) => x.getFullYear()}
        />
        <VictoryAxis
          dependentAxis
          domain={[-10, 15]}
          offsetX={50}
          orientation="left"
          standalone={false}
        />
        <VictoryLine
          data={[
            { x: new Date(2000, 1, 1), y: 0 },
            { x: new Date(2004, 6, 1), y: 0 }
          ]}
          domain={{
            x: [new Date(2000, 1, 1), new Date(2004, 1, 1)],
            y: [-10, 15]
          }}
          scale={{ x: "time", y: "linear" }}
          standalone={false}
        />
        <VictoryLine
          data={dataSetOne}
          domain={{
            x: [new Date(2000, 1, 1), new Date(2004, 1, 1)],
            y: [-10, 15]
          }}
          interpolation="monotoneX"
          scale={{ x: "time", y: "linear" }}
          standalone={false}
        />
        <VictoryAxis
          dependentAxis
          domain={[0, 50]}
          orientation="right"
          standalone={false}
        />
        <VictoryLine
          data={dataSetTwo}
          domain={{
            x: [new Date(2000, 1, 1), new Date(2004, 1, 1)],
            y: [0, 50]
          }}
          interpolation="monotoneX"
          scale={{ x: "time", y: "linear" }}
          standalone={false}
        />
      </g>
    </svg>
  );
}

We get our data for the lines with the functions.

Then we add the labels with the VictoryLabel components.

We set the x and y props to set their positions.

Then we put our chart components in the g element.

VictoryAxis renders the x-axis.

We set the scale to 'time' to render the dates on the axis.

Also, we set the offsetX to shift the axis.

The first VictoryLine has renders a horizontal line.

We set the data prop to set the data.

Also, we set the x and y domain to set the range of values to show on the axis.

scale is set individually for x and y since they have different scales.

And we set standalone to false so we can add more to the chart.

Then add another VictoryLine to render the data from dataSetOne .

We add another VictoryAxis to put a y-axis on the right side. And we set their own domain.

Then add another VictoryLine to render the data from dataSetTwo.

Now we get a line chart with 3 lines, one y-axis each on each side, an x-axis at the bottom, and labels at the top of the chart.

Conclusion

We can add custom charts with the components that comes with Victory in our React app.