Building and Rendering charts with Nivo in React

Isaac Okoro
StackAnatomy

--

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. In this tutorial, we 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. 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.

Another issue is that you will be importing quite a large bundle size when using D3, which negatively impacts page load, and when building with D3, you tend to write lots of code for rendering a basic line chart and if you want to build something like a stream or calendar chart, it becomes bulky thereby making the code more complex and more challenging to maintain and debug.

Why use Nivo instead of other data visualization libraries

Nivo has a dedicated documentation site that is interactive 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, then you can render it in isomorphic rendering. 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. That’s because, as we said earlier, Nivo has code-splitting features that allow for the movement of small packages instead of the whole library, and that 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 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.jsexport 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.jsximport { 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 also the ResponsiveStream from nivo. We also defined some properties for our stream component and passed our data to the stream chart.

// App.jsimport 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 up the development server on localhost:3000.

yarn start

The results should look like the image below:

Note: There are no negative goals, we are showing the goals using a stream chart and we want to make it clearly visible the goals scored by each person. Look out for the peaks and the shallow periods for the total values over time. Pick the colours and look for peaks and troughs to identify patterns or outliers. Here is a link to learn more on Stream charts and how to read them.

Open Source Session Replay

Debugging a web application in production may be challenging and time-consuming. OpenReplay is an Open-source alternative to FullStory, LogRocket and Hotjar. It allows you to monitor and replay everything your users do and shows how your app behaves for every issue. It’s like having your browser’s inspector open while looking over your user’s shoulder. OpenReplay is the only open-source alternative currently available.

Happy debugging, for modern frontend teams — Start monitoring your web app 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.jsexport 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 also our created data.

// Calendar.jsximport { 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 also the ResponsiveCalendar from Nivo. Then we defined properties for our data from the margin to the colors and also 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.jsimport { 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

In this article, we learnt 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.

Resources

--

--