Building and Rendering charts with Nivo in React
Data visualization is an essential tool when building web applications as it seeks to grab viewers’ interest and keep their eyes on the message. This is one of the things developers endeavor to develop and use in their web applications. This tutorial will discuss Nivo as a solution to data visualization in React applications by building charts and knowing how to implement them in your React application. Nivo is open source with more than 9.1k stars on Github.
What is Nivo
According to its official documentation,
Nivo provides supercharged React components to easily build Dataviz apps; it’s built on top of d3. Several libraries already exist for React d3 integration, but only a few provide server-side rendering ability and fully declarative charts.
Nivo is a robust and well-documented data visualization library built with d3. It is a package that leverages d3 to make beautiful, responsive data visualizations in React applications. It has helpful documentation, interactive widgets, and lots of examples of how to solve complex problems.
Concept of Nivo
Nivo aims to provide beautiful and eye-catching graphs and charts that are easy to use and incorporate into your next react application. Its server rendering ability is top-notch, and it’s a solution to your data visualization needs.
Problems with using D3 in React
D3 is one of the top libraries for creating, manipulating, and visualizing data. There are still some problems associated with using it, and one of them is that it has a steep learning curve and requires learning many concepts about D3. It may take days to learn how to create a chart instead of being easy to use.
Another issue is that React and D3 both manipulate the DOM, and it is advisable (when using React) to not mess around with the DOM. So when using D3 in React and you change or influence its DOM manipulating function, you are changing the real DOM, which means that you are sacrificing most of what React has to offer in terms of efficiency and performance.
Yet another issue is that you will be importing quite a large bundle size when using D3, which negatively impacts page load. When building with D3, you tend to write lots of code for rendering a basic line chart. If you want to build something like a stream or calendar chart, it becomes bulky, making the code more complex and challenging to maintain and debug.
Why use Nivo instead of other data visualization libraries
Nivo has a dedicated interactive documentation site and includes lots of examples. It also customizes attributes and shows a live simulation of each chart directly in the site’s UI.
Nivo also has a code splitting feature. It is put into smaller packages that allow individual charts component loading instead of parsing through the entire library, which ultimately results in a better performance.
Nivo also gives you different options for server-side rendering. If you have lots of data, you can render it in isomorphic rendering, and there is also the option of rendering in canvas or SVGs.
Installing Nivo
Before we install Nivo in our application, we will create a new React application using the command below:
npx create-react-app Nivo-app
Next, we will install Nivo into our React application using the yarn package manager in the code block below:
yarn add @nivo/core
The code above will only install the core package without the entire library component. As we said earlier, Nivo has code-splitting features that allow for the movement of small packages instead of the whole library, which means that we can add a specific package when we need to use a particular component.
Let’s go ahead and add the first Nivo component to our application.
Building Stream Chart with Nivo
Stream charts are ideal for displaying high-volume datasets to discover trends and patterns over time across a wide range of categories. To build a stream chart with Nivo in our React application, we first install the stream package from Nivo to enable us to build our stream chart. Let’s do this below:
yarn add @nivo/stream
In the source folder of our app, we will create a streamData.js
file and populate the file with the data which will be used in our Stream chart, as shown below:
// streamData.js
export const streamData = [
{
Ronaldo: 116,
Neymar: 17,
Messi: 37,
},
{
Ronaldo: 101,
Neymar: 11,
Messi: 54,
},
{
Ronaldo: 156,
Neymar: 166,
Messi: 141,
},
{
Ronaldo: 196,
Neymar: 160,
Messi: 63,
},
{
Ronaldo: 173,
Neymar: 167,
Messi: 94,
},
{
Ronaldo: 103,
Neymar: 194,
Messi: 188,
},
{
Ronaldo: 114,
Neymar: 105,
Messi: 40,
},
{
Ronaldo: 55,
Neymar: 12,
Messi: 49,
},
{
Ronaldo: 78,
Neymar: 29,
Messi: 90,
},
];
Next, we create a Stream.jsx
file, and inside we will import the stream
component and then kick off the creation of our stream chart.
// Stream.jsx
import { ResponsiveStream } from "@nivo/stream";
import { streamData } from "../streamData";
const Stream = () => {
return (
<div style={{ height: "400px" }}>
<h2>My Awesome Stream</h2>
<ResponsiveStream
data={streamData}
keys={["Ronaldo", "Neymar", "Messi"]}
margin={{
top: 50,
right: 180,
bottom: 50,
left: 100,
}}
axisTop={null}
axisRight={null}
axisBottom={{
orient: "bottom",
tickSize: 5,
tickPadding: 5,
tickRotation: 0,
legend: "Number of Years Playing",
legendOffset: 36,
}}
axisLeft={{
orient: "left",
tickSize: 5,
tickPadding: 5,
tickRotation: 0,
legend: "Number of Goals",
legendOffset: -40,
}}
offsetType="silhouette"
colors={{ scheme: "accent" }}
fillOpacity={0.85}
borderColor={{ theme: "background" }}
dotBorderColor={{
from: "color",
modifiers: [["darker", 0.7]],
}}
legends={[
{
anchor: "bottom-right",
direction: "column",
translateX: 100,
itemWidth: 80,
itemHeight: 20,
itemTextColor: "#999999",
symbolSize: 12,
symbolShape: "circle",
effects: [
{
on: "hover",
style: {
itemTextColor: "#000000",
},
},
],
},
]}
/>
<footer>
<p>
Representing football goals stats with Nivo stream
</p>
<p
style={{
fontStyle: "oblique",
marginTop: "0.5rem",
}}
>
PS: Not real stats
</p>
</footer>
</div>
);
};
export default Stream;
In the code block above, we imported the streamData
to populate our stream chart and the ResponsiveStream
from nivo. We also defined some properties for our stream component and passed our data to the stream chart.
// App.js
import Stream from "./components/stream";
const App = () => {
return (
<div>
<Stream />
</div>
);
};
export default App;
In our App.js
file, we import the stream component and then run the command below to start the development server on localhost:3000
.
yarn start
The results should look like the image below:
Note: Look out for the peaks and the shallow periods for the total values over time. Look at the overall shape of the stream to see if there are seasonal patterns. Pick the colors and look for peaks and troughs to identify patterns or outliers. There are no negative goals; we are showing the goals using a stream chart, and we want to make clearly visible the goals scored by each person. Here is a link to learn more about reading Stream charts.
Open Source Session Replay
OpenReplay is an open-source, session replay suite that lets you see what users do on your web app, helping you troubleshoot issues faster. OpenReplay is self-hosted for full control over your data.
Start enjoying your debugging experience - start using OpenReplay for free.
Building a Calendar with responsiveCalendar component
A calendar chart is a visualization tool that shows activity over a long period, such as months or years. To build a calendar chart with Nivo in our React application, we will install the calendar package from Nivo to build our calendar chart. Let’s do this below:
yarn add @nivo/calendar
Next, we create a calendarData.js
file which will contain all the data for the population of the calendar chart.
// calendarData.js
export const calendarData = [
{
value: 290,
day: "2021-03-03",
},
{
value: 289,
day: "2021-03-14",
},
{
value: 316,
day: "2021-04-08",
},
{
value: 297,
day: "2021-02-10",
},
{
value: 256,
day: "2021-04-02",
},
{
value: 49,
day: "2021-07-15",
},
{
value: 374,
day: "2021-05-11",
},
{
value: 55,
day: "2021-08-09",
},
{
value: 274,
day: "2021-05-19",
},
{
value: 20,
day: "2021-03-28",
},
{
value: 29,
day: "2021-07-04",
},
{
value: 374,
day: "2021-01-11",
},
{
value: 377,
day: "2021-03-27",
},
{
value: 371,
day: "2021-02-15",
},
{
value: 327,
day: "2021-05-28",
},
{
value: 289,
day: "2021-03-12",
},
{
value: 335,
day: "2021-03-21",
},
{
value: 119,
day: "2021-06-14",
},
{
value: 369,
day: "2021-08-04",
},
{
value: 116,
day: "2021-06-11",
},
{
value: 294,
day: "2021-04-29",
},
{
value: 381,
day: "2021-01-23",
},
{
value: 223,
day: "2021-05-24",
},
// More and more pieces of data as the case may be
];
Next, we will create a Calendar.jsx
file and then import the ResponsiveCalendar
component from Nivo and our created data.
// Calendar.jsx
import { ResponsiveCalendar } from "@nivo/calendar";
import { calendarData } from "../calendarData";
const Calendar = () => {
return (
<div style={{ height: 400 }}>
<h2>Nivo Calendar</h2>
<ResponsiveCalendar
data={calendarData}
from="2021-01-08"
to="2021-08-09"
emptyColor="#eeeeee"
colors={[
"#61cdbb",
"#97e3d5",
"#e8c1a0",
"#f47560",
]}
margin={{
top: 40,
right: 40,
bottom: 40,
left: 40,
}}
yearSpacing={40}
monthBorderColor="#ffffff"
dayBorderWidth={2}
dayBorderColor="#ffffff"
legends={[
{
anchor: "bottom-right",
direction: "row",
translateY: 36,
itemCount: 4,
itemWidth: 42,
itemHeight: 36,
itemsSpacing: 14,
itemDirection: "right-to-left",
},
]}
/>
</div>
);
};
export default Calendar;
In the code block above, we imported the calendarData
and the ResponsiveCalendar
from Nivo. Then we defined properties for our data from the margin to the colors and passed the calendarData
to the chart.
Finally, we import the calendar component into our App.js
file. We also added some routing to make everything look good.
// App.js
import {
BrowserRouter,
Route,
Switch,
NavLink,
} from "react-router-dom";
import Calendar from "./components/calendar";
import Stream from "./components/stream";
const App = () => {
return (
<BrowserRouter>
<nav>
<NavLink
exact
activeStyle={{ textDecoration: "underline" }}
to="/"
>
Stream
</NavLink>
<NavLink
exact
activeStyle={{ textDecoration: "underline" }}
to="/calendar"
>
Calendar
</NavLink>
</nav>
<Switch>
<Route exact path="/" component={Stream} />
<Route
exact
path="/calendar"
component={Calendar}
/>
</Switch>
</BrowserRouter>
);
};
export default App;
Our final results should look like the image below:
Here is a link to the code on Github, and a live version of the app can be found here.
Conclusion
This article taught us about Nivo, a robust and well-documented data visualization library that provides a better experience through beautiful charts. We had a glimpse of what we could achieve with Nivo. Have fun using Nivo and its various components for your next React application.