Visx is a library that lets us add graphics to our React app easily.
In this article, we’ll look at how to use it to add horizontal grouped bar charts into our React app.
Install Required Packages
We have to install a few modules to create the grouped bar chart.
To get started, we run:
npm i @visx/axis @visx/group @visx/mock-data @visx/responsive @visx/scale @visx/shape
to install the packages.
Create the Chart
We can create the chart by adding the items provided by the modules.
We use the data from the @visx/mock-data module.
To create the chart, we write:
import React from "react";
import { BarGroupHorizontal, Bar } from "@visx/shape";
import { Group } from "@visx/group";
import { AxisLeft } from "@visx/axis";
import cityTemperature from "@visx/mock-data/lib/mocks/cityTemperature";
import { scaleBand, scaleLinear, scaleOrdinal } from "@visx/scale";
import { timeParse, timeFormat } from "d3-time-format";
const blue = "#aeeef8";
const green = "#e5fd3d";
const purple = "#9caff6";
const background = "#612efb";
const defaultMargin = { top: 20, right: 20, bottom: 20, left: 50 };
const parseDate = timeParse("%Y-%m-%d");
const format = timeFormat("%b %d");
const formatDate = (date) => format(parseDate(date));
function max(arr, fn) {
return Math.max(...arr.map(fn));
}
const data = cityTemperature.slice(0, 4);
const keys = Object.keys(data[0]).filter((d) => d !== "date");
const getDate = (d) => d.date;
const dateScale = scaleBand({
domain: data.map(getDate),
padding: 0.2
});
const cityScale = scaleBand({
domain: keys,
padding: 0.1
});
const tempScale = scaleLinear({
domain: [0, max(data, (d) => max(keys, (key) => Number(d[key])))]
});
const colorScale = scaleOrdinal({
domain: keys,
range: [blue, green, purple]
});
function Example({ width, height, margin = defaultMargin, events = false }) {
const xMax = width - margin.left - margin.right;
const yMax = height - margin.top - margin.bottom;
dateScale.rangeRound([0, yMax]);
cityScale.rangeRound([0, dateScale.bandwidth()]);
tempScale.rangeRound([0, xMax]);
return width < 10 ? null : (
<svg width={width} height={height}>
<rect
x={0}
y={0}
width={width}
height={height}
fill={background}
rx={14}
/>
<Group top={margin.top} left={margin.left}>
<BarGroupHorizontal
data={data}
keys={keys}
width={xMax}
y0={getDate}
y0Scale={dateScale}
y1Scale={cityScale}
xScale={tempScale}
color={colorScale}
>
{(barGroups) =>
barGroups.map((barGroup) => (
<Group
key={`bar-group-horizontal-${barGroup.index}-${barGroup.y0}`}
top={barGroup.y0}
>
{barGroup.bars.map((bar) => (
<Bar
key={`${barGroup.index}-${bar.index}-${bar.key}`}
x={bar.x}
y={bar.y}
width={bar.width}
height={bar.height}
fill={bar.color}
rx={4}
onClick={() => {
if (events)
alert(
`${bar.key} (${bar.value}) - ${JSON.stringify(bar)}`
);
}}
/>
))}
</Group>
))
}
</BarGroupHorizontal>
<AxisLeft
scale={dateScale}
stroke={green}
tickStroke={green}
tickFormat={formatDate}
hideAxisLine
tickLabelProps={() => ({
fill: green,
fontSize: 11,
textAnchor: "end",
dy: "0.33em"
})}
/>
</Group>
</svg>
);
}
export default function App() {
return (
<div className="App">
<Example width="500" height="300" />
</div>
);
}
We set the colors of the bars with the blue , green and purple variables.
The background variable has the background color.
defaultMargin have the default margins.
parseDate and format have the date parsing and formatting functions.
We parse the date from the mock data so we can format them to display in the chart.
data has the data for the chart.
keys have the data for the x-axis.
dateScale have the date scale.
cityScale have the city data.
tempScale have the temperature values for the bars.
colorScale have the colors for the bars.
We computed the xMax and yMax values to get the max values for the x and y axes.
Then we call rangeRound to set the max values for the x and y-axis ranges.
Next, we return the svg element and add the chart parts inside to add the bar.
The Group component is the container for the bar parts.
BarGroupHorizontal lets us display the bar groups horizontally.
We set the color , width , and the scales for the bars with the y0 , y0Scale and y1Scale props.
xScale sets the x-axis scale which is the bar scale.
Then we map the barGroups to return the Bar s in the map callback.
We set the bar lengths with the width prop.
Finally, we add the AxisLeft component to render the y-axis.
Conclusion
We can use the modules provided by Visx to create a horizontal grouped bar chart in our React app.