Summary

As a business owner, ensuring your data displays captivatingly is crucial. Regarding web development, the two libraries that have taken up the mantle to enable you to achieve this include ReactJS and D3. These libraries have been of significant efficacy for individuals building lively, data-packed web apps. This blog post will show how D3js and React Integration can help level up your web application with incredible features and next-gen performance.

Table of Contents

Overview of D3.js

  • D3.js stands for Data-Driven Documents. This open-source library lets you breathe life into your data using HTML, SVG, and CSS. Pretty cool, right?
  • With D3.js by your side, you’re not just plotting numbers on a chart but creating interactive and dynamic web experiences for the people.
  • Your apps take huge chunks of data and turn them into great visual images. That’s what D3 JS is all about! It tweaks the Document Object Model (DOM) based on your data, letting your web applications update their content and look and feel in real-time as users interact with them or as the data itself changes.

Benefits of using D3.js

  • It’s a powerful tool specially designed for data handling and designing data visualizations.
  • It’s compatible with Angular.js, React.js, and Ember.js, making it adaptable to different project requirements.
  • As an open-source platform, D3 allows developers to explore the source code, customize it, and use it according to their needs.
  • Seamless integration with fundamental web technologies like HTML, CSS, and SVG.
  • This inherent flexibility allows developers complete control over their visualizations, allowing them to alter and fine-tune the output according to their preferences.
  • It’s faster than popular visualization tools like Chart.js, Tableau, or QlikView.
  • Its speed and efficiency make it well-suited for handling even the largest and most complex datasets, ensuring optimal performance for large datasets.

Now that we know all the aspects of D3.js let us jump to the steps to integrate D3 JS in React.

Integrating D3.js with React

D3.js and React are both UI libraries for manipulating DOM and managing UI elements, but they work differently. However, before we integrate D3.js with React, you must ensure that you have installed Node JS version 18 or higher. If not, you can install it using nvm or PNPM.

Setting up a React App

Since the release of React 18, significant improvements have been made to the core of React JS, and `create react app` is now an old way of creating new projects.

Many advanced frameworks built on React offer routing, data fetching, code bundling, and more out of the box. Ideally, we usually require these advanced features when we work on larger datasets.

Note: Depending on your needs and product requirements, the React team recommends using frameworks like Next.js, Remix, Gatsby, and Vite.

Here, we are going with ViteJS.

What is ViteJs?

  • It’s a tool for modern and advanced web projects, prioritizing speed and efficiency.
  • It includes a development server called Hot Module Replacement (HMR) and a build command that utilizes Rollup to generate optimized production assets.
  • It also comes with predefined settings that you can choose from, which can be tailored to specific needs through configuration options.
  • Additionally, it gives you seamless integration with modern frameworks and other tools through plugins.
  • Vite provides both programmatic APIs and JavaScript APIs, offering comprehensive typing support.

Moving ahead, go to your terminal and run the following command:

Copy Text
 npm create vite@latest

Then, give a project name, select React as the framework, and choose the JavaScript variant.

giving a project name

Then go to the project folder and open it in your preferred code editor to start the codebase.

Let us now install D3.js.

Copy Text
npm install d3

By default, ⁠App.jsx is the main entry point rendered on the browser. If you see any existing content in App.jsx, remove it. Let’s look at a few examples.

Examples of React D3 Integration

🟠 Bar Chart

Bar chart

For React JS D3 charts, we will first define variables such as margin, inner width, height, and a React ref.

Copy Text
const margin = { top: 20, right: 20, bottom: 20, left: 20 };
const innerWidth = width - margin.left - margin.right;
const innerHeight = height - margin.top - margin.bottom;
const ref = useRef();

The ref is a React reference that will be utilized to select the SVG element within the DOM.

Copy Text
useEffect(() => {
    //Chart generation code goes here...
}, [data, width, height]);

The useEffect hook is used to run side effects within a component. In this case, it is utilized to create a bar chart when the component mounts for the first time and to update it when value changes occur to the data, width, or height props.

Copy Text
const xScale = d3
      .scaleBand()
      .domain(data.map((d) => d.name))
      .range([0, innerWidth])
      .padding(0.1);

const yScale = d3
      .scaleLinear()
      .domain([0, d3.max(data, (d) => d.value)])
      .range([innerHeight, 0]);

Within the useEffect hook, the SVG element is initially targeted using the ref. The x-scale, specifically, is configured as a band scale for discrete name values within the data.

The x-scale is frequently utilized in bar charts, where each bar corresponds to a distinct value, such as a category or name.

The y-scale allows a linear scale to represent continuous values within the data.

The domain() function establishes the input domain applied to the x-scale; it iterates through the data array and returns an array comprising the name properties.

The x-scale will have a discrete value corresponding to each unique name in the data, and the y-scale will contain the value properties from the data. Hence, the y-scale will have discrete values equivalent to the unique values present in the data.

The range() function establishes the output range for the scale.

The x-scale sets the range from 0 to innerWidth, representing the width of the chart area. The y-scale sets the range from innerHeight to 0.

This is a usual practice in D3.js for flipping the y-axis, ensuring higher values are positioned on the screen, which contrasts with the standard behavior of pixel values in web browsers.

Next, let’s create bars using Rectangle.

Copy Text
 svg
    .selectAll("rect")
    .data(data)
    .enter()
    .append("rect")
    .attr("x", (d) => xScale(d.name))
    .attr("y", (d) => yScale(d.value))
    .attr("width", xScale.bandwidth())
    .attr("height", (d) => innerHeight - yScale(d.value))
    .attr("fill", "blue");

Here, the selectAll(“rect”) method identifies and selects all rectangle elements within the SVG container, and the data(data) function links the provided data to these elements.

Following this, It’s required to add the enter() method to generate a selection of elements that should be added to match the new data points.

You must use the append(“rect”) function to add a rectangle element to each new data point. The attr() function is also utilized to assign various attributes to these rectangles.

The “x” and “y” attributes, denoting the position of the rectangles, are determined using the x and y scales along with the given data.

However, the width attribute, which determines the width of the rectangles, is set based on the bandwidth of the x scale. Meanwhile, the height attribute, which defines the height of the rectangles, is determined by the inner height of the chart, the y scale, and the data. Additionally, the fill attribute, responsible for the rectangles’ color, is set to blue.

Copy Text
svg
    .append("g")
    .attr("transform", `translate(0,${innerHeight})`)
    .call(d3.axisBottom(xScale));

  svg
    .append("g")
    .attr("transform", `translate(${margin.left}, 0)`)
    .call(d3.axisLeft(yScale));
Looking To Develop A React JS App With Data Visualization Metrics?

Hire ReactJS Developers from us and leverage the true potential of D3.js and React Integration for captivating Data Visualization Features.

Next, a group element is added to the SVG container to represent the x-axis, using the attr(“transform”) function to utilize the group element’s position at the bottom of the chart. Inside this group element, the call(d3.axisBottom(xScale)) function generates the x-axis using the specified x-scale.

Copy Text
svg.attr("width", width).attr("height", height);

You can create a y-axis using a similar process but without transforming since it’s already positioned on the left side of the chart.

Meanwhile, the critical point is to add the width and height attributes of the SVG container and assign the values of the width and height props, defining the overall size of the chart.

Copy Text
return () => {
    svg.selectAll("*").remove();
};

Now that we are almost done creating a bar chart. Before we run our code, we must add a cleanup function that removes all the elements from the SVG container. This is a must because we have added a side effect.

The cleanup function is returned from a useEffect hook, meaning it executes when the component is unmounted from the DOM and before re-running the effect due to changes in dependencies.

In our scenario, it removes all elements from the SVG container before the component is unmounted or before the effect is re-run for new elements representing updated data.

Thus, the final code for the BarChart component appears as follows.

Copy Text
import { useRef, useEffect } from "react";
import * as d3 from "d3";

const BarChart = ({ data, width, height }) => {
  const margin = { top: 20, right: 20, bottom: 20, left: 20 };
  const innerWidth = width - margin.left - margin.right;
  const innerHeight = height - margin.top - margin.bottom;
  const ref = useRef();

  useEffect(() => {
    const svg = d3.select(ref.current);

    const xScale = d3
      .scaleBand()
      .domain(data.map((d) => d.name))
      .range([0, innerWidth])
      .padding(0.1);

    const yScale = d3
      .scaleLinear()
      .domain([0, d3.max(data, (d) => d.value)])
      .range([innerHeight, 0]);

    svg
      .selectAll("rect")
      .data(data)
      .enter()
      .append("rect")
      .attr("x", (d) => xScale(d.name))
      .attr("y", (d) => yScale(d.value))
      .attr("width", xScale.bandwidth())
      .attr("height", (d) => innerHeight - yScale(d.value))
      .attr("fill", "blue");

    svg
      .append("g")
      .attr("transform", `translate(0,${innerHeight})`)
      .call(d3.axisBottom(xScale));

    svg
      .append("g")
      .attr("transform", `translate(${margin.left}, 0)`)
      .call(d3.axisLeft(yScale));

    svg.attr("width", width).attr("height", height);

    return () => {
      svg.selectAll("*").remove();
    };
  }, [data, width, height]);

  return <svg ref={ref} />;
};

export default BarChart;

We need to use the BarChart React component in the ⁠App component. We’ll begin by importing BarChart from the components folder. Additionally, we must define an array of data to display, along with width and height as props.

Copy Text
import "./App.css";
import BarChart from "./components/BarChart";

function App() {
  return (
    <>
      <h2> D3 Charts in React</h2>
      <div className="App">
        <BarChart
          data={[
            { name: "foo", value: 10 },
            { name: "bar", value: 20 },
            { name: "baz", value: 30 },
            { name: "qux", value: 40 },
          ]}
          width={800}
          height={600}
        />
      </div>
    </>
  );
}

export default App;

🟠 Pie Chart

Now, we will generate a pie chart using the same data with D3 JS in React. This will enhance our understanding of how to utilize D3.js in an alternative manner.

Pie chart

Using React with D3 first, we’ll establish the variables for margins, the inner width and height of the chart, and a React reference similar to the one used for the Barchart. Additionally, we’ll define a tooltip variable to display the value of each pie element when hovered over. We’ll create a < div > element with the id=”tooltip” within the App component to do this.

Copy Text
<div id="tooltip" style={{ opacity: 0, position: "absolute" }} />

Within the ⁠useEffect hook in PieChart.jsx

Copy Text
const arc = d3
      .arc()
      .innerRadius(0)
      .outerRadius(Math.min(innerWidth, innerHeight) / 2 - 1);

const pie = d3
      .pie()
      .sort(null)
      .value((d) => d.value);

const arcs = pie(data);

The arc constant represents a D3 arc generator. It’s set up to create arcs with an inner radius of 0, effectively creating a pie chart rather than a donut chart. The outer radius is also determined to be half the smaller dimension between innerWidth and innerHeight, ensuring that the pie fits neatly within the SVG container.

Similarly, the pie constant denotes a D3 pie layout generator. It’s configured not to sort the data (sort(null)) and to use the value property of each data object to determine the size of each slice (value((d) => d.value)).

Finally, the arcs constant is an array of arc descriptors created by passing the data array to the pie layout generator.

Copy Text
const g = svg
     .selectAll(".arc")
     .data(arcs)
     .enter()
     .append("g")
     .attr("class", "arc")
     .attr("transform", `translate(${innerWidth / 2},${innerHeight / 2})`);

The g constant represents a D3 selection comprising new group elements, each corresponding to an arc. Every ⁠g element is translated to the center of the SVG.

Copy Text
g.append("path")
      .attr("fill", (d, i) => d3.schemeCategory10[i])
      .attr("d", arc)
      .on("mouseover", (event, d) => {
        tooltip
          .style("opacity", 1)
          .style("left", `${event.pageX}px`)
          .style("top", `${event.pageY}px`)
          .text(`Value: ${d.value}`);
      })
      .on("mouseout", () => {
        tooltip.style("opacity", 0);
      });

 g.append("text")
      .attr("transform", (d) => `translate(${arc.centroid(d)})`)
      .attr("text-anchor", "middle")
      .attr("dy", "0.35em") // vertically center text
      .text((d) => d.data.name);

    svg.attr("width", width).attr("height", height);

The ‘g’ elements have the path elements appended to them. These paths are filled with colors from the d3.schemeCategory10 array, and their d attribute, which describes the arc path, is set using the arc generator. We also must add event listeners for mouseover and mouseout to display and hide a tooltip.

In addition, for D3 JS in React, text elements are added to each group element. They are translated to the centroid of their corresponding arc, and their text content is set to the name property of the associated data object.

Thus, the final code for the PieChart component appears as follows.

Copy Text
import { useEffect, useRef } from "react";
import * as d3 from "d3";

const PieChart = ({ data, width, height }) => {
  const margin = { top: 20, right: 20, bottom: 20, left: 20 };
  const innerWidth = width - margin.left - margin.right;
  const innerHeight = height - margin.top - margin.bottom;
  const ref = useRef();
  const tooltip = d3.select("#tooltip");

  useEffect(() => {
    const svg = d3.select(ref.current);

    const arc = d3
      .arc()
      .innerRadius(0)
      .outerRadius(Math.min(innerWidth, innerHeight) / 2 - 1);

    const pie = d3
      .pie()
      .sort(null)
      .value((d) => d.value);

    const arcs = pie(data);

    const g = svg
      .selectAll(".arc")
      .data(arcs)
      .enter()
      .append("g")
      .attr("class", "arc")
      .attr("transform", `translate(${innerWidth / 2},${innerHeight / 2})`);

    g.append("path")
      .attr("fill", (d, i) => d3.schemeCategory10[i])
      .attr("d", arc)
      .on("mouseover", (event, d) => {
        tooltip
          .style("opacity", 1)
          .style("left", `${event.pageX}px`)
          .style("top", `${event.pageY}px`)
          .text(`Value: ${d.value}`);
      })
      .on("mouseout", () => {
        tooltip.style("opacity", 0);
      });

    g.append("text")
      .attr("transform", (d) => `translate(${arc.centroid(d)})`)
      .attr("text-anchor", "middle")
      .attr("dy", "0.35em") // vertically center text
      .text((d) => d.data.name);

    svg.attr("width", width).attr("height", height);

    return () => {
      svg.selectAll("*").remove();
    };
  }, [data, width, height]);

  return <svg ref={ref} />;
};

export default PieChart;

Best Practices For Using React with D3

  • For your ReactJS and D3 integration, You should consider implementing debouncing or throttling to handle intensive and real-time calculations and animations. This will help your application remain smooth and responsive even with large datasets.
  • Always utilize cleanup functions to reduce unnecessary calculations and re-renders. These are expensive and time-consuming and negatively impact the user experience.

Final Thoughts

This blog post deeply explored the ReactJS and D3 integrations and how D3.js works with React.js applications. Mastering D3.js requires familiarizing yourself with its distinct syntax and lots of practice. However, as a business owner, if you want to understand if this can benefit your ReactJS business application, you can contact a leading React JS Development Company and get started today!

Frequently Asked Questions (FAQs)

To create interactive and meaningful visualizations that are both effective and engaging, we need to manage the state and its data flow. It guarantees that updating data will prompt the correct re-renders while also allowing D3.js to respond to changes in state.

D3 JS does not have many disadvantages, but learning to visualize data takes time and effective use of D3 JS requires prior knowledge of HTML, CSS, SVG, and DOM manipulation.

Since React controls the virtual DOM, direct DOM manipulation by D3.js can lead to conflicts and unexpected behavior. You must carefully handle updates and ensure operations do not interfere with React’s rendering process. Tip: Use cleanup functions.

Performance optimization is essential when integrating D3 JS in React, especially for applications dealing with large datasets or complex visualizations. Techniques like debouncing or throttling can help mitigate performance issues by limiting the frequency of updates and calculations to some extent.

Get Instant Time And Cost Estimation For Your React Project

CONTACT US!

Build Your Agile Team

Hire Skilled Developer From Us

[email protected]

Your Success Is Guaranteed !

We accelerate the release of digital product and guaranteed their success

We Use Slack, Jira & GitHub for Accurate Deployment and Effective Communication.

How Can We Help You?