Building and Rendering charts with Nivo in React

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 endeavour 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: Stream chart with responsivestream component

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

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.

image.png

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.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:

Calendar chart with responsiveCalendar component

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.

Resources