Skip to content

Contact sales

By filling out this form and clicking submit, you acknowledge our privacy policy.

Loading Remote Chart Data for D3.js in a React App

In this guide, shows you how to process three different data formats using D3-fetch, a simple wrapper around the standard fetch API built into modern browsers.

Sep 24, 2020 • 11 Minute Read

Introduction

At the heart of D3.js is joining data to visualizations in order to easily understand and interpret large datasets. Usually, these datasets are dynamic and come in different formats.

In this guide, you will learn how to process different data formats using D3-fetch in a React app. D3-fetch is a simple wrapper around the standard fetch API built into modern browsers; it makes it more convenient to interact with different file formats.

This guide builds on a previous guide, Using D3.js Inside a React App, where you learn how to set up a simple bar chart in D3.js using static in-memory data. Here, you will learn about accessing JSON, CSV, and XML remote data formats and bind them to your chart. The data is sourced from the Bureau of Transportation Statistics.

Fetch CSV Data

Comma-separated values (CSV) is a common format for sharing data as it is simple and easy to understand. To start fetching remote CSV data, start a React app and place a CSV file in the /public folder to serve it locally. To do this run:

      yarn start
    

Then create a the file public/chart-data.csv and paste the following contents.

      year,efficiency,sales
1980,24.3,8949000
1985,27.6,10979000
1990,28,9303000
1991,28.4,8185000
1992,27.9,8213000
1993,28.4,8518000
1994,28.3,8991000
1995,28.6,8620000
1996,28.5,8479000
1997,28.7,8217000
1998,28.8,8085000
1999,28.3,8638000
2000,28.5,8778000
2001,28.8,8352000
2002,29,8042000
2003,29.5,7556000
2004,29.5,7483000
2005,30.3,7660000
2006,30.1,7762000
2007,31.2,7562000
2008,31.5,6769000
2009,32.9,5402000
2010,33.9,5636000
2011,33.1,6093000
2012,35.3,7245000
2013,36.4,7586000
2014,36.5,7708000
2015,37.2,7517000
2016,37.7,6873000
2017,39.4,6081000
    

You can now navigate to https://localhost:3000/chart-data.csv to see your data being served locally.

With a CSV file being served, you can modify your React code and display its data in a chart.

Update src/App.js to the below code to fetch CSV data.

      import React from "react";
import BarChart from "./BarChart";
import * as d3 from "d3";
import "./App.css";

function App() {
  const [data, setData] = React.useState([]);
  const [loading, setLoading] = React.useState(true);

  React.useEffect(() => {
    d3.csv("/chart-data.csv").then((d) => {
      setData(d);
      setLoading(false);
    });
    return () => undefined;
  }, []);

  return (
    <div className="App">
      <header className="App-header">
        {loading && <div>loading</div>}
        {!loading && <BarChart data={data} />}
      </header>
    </div>
  );
}

export default App;
    

The code snippet above demonstrates fetching CSV data when the App component is loaded. When the component is loaded, the default state is loading=true and a request is made to localhost:3000/chart-data.csv to fetch the data. When the fetch request is complete, it will update the state of the application to loading=false and display the BarChart component passing down the retrieved data.

Retrieve JSON Data

JSON is another popular format for sharing data. Compared to CSV, it allows hierarchical data types but is more verbose. To start serving JSON, create the file public/chart-data.json and add the following contents.

      
  {"year": 1980
    

You have created a JSON file, and it is served at https://localhost:3000/chart-data.json, similar to the CSV sample. To start fetching this data, you only need to make minor modifications to App.js. It will look like the code snippet below:

      import React from "react";
import BarChart from "./BarChart";
import * as d3 from "d3";
import "./App.css";

function App() {
  const [data, setData] = React.useState([]);
  const [loading, setLoading] = React.useState(true);

  React.useEffect(() => {
    d3.json("/chart-data.json").then((d) => {
      setData(d);
      setLoading(false);
    });
    return () => undefined;
  }, []);

  return (
    <div className="App">
      <header className="App-header">
        {loading && <div>loading</div>}
        {!loading && <BarChart data={data} />}
      </header>
    </div>
  );
}

export default App;
    

Note that you have only changed the URL to /chart-data.json and the function call from d3.csv to d3.json.

Fetch XML Data

Another common data format is XML. This can be more verbose, therefore it is not preferred for new development and is more commonly used in older legacy systems. To serve this format, create the file public/chart-data.xml and add the following contents.

      <?xml version="1.0" encoding="UTF-8"?>
<root>
   <element>
      <efficiency>24.3</efficiency>
      <sales>8949000</sales>
      <year>1980</year>
   </element>
   <element>
      <efficiency>27.6</efficiency>
      <sales>10979000</sales>
      <year>1985</year>
   </element>
   <element>
      <efficiency>28</efficiency>
      <sales>9303000</sales>
      <year>1990</year>
   </element>
   <element>
      <efficiency>28.4</efficiency>
      <sales>8185000</sales>
      <year>1991</year>
   </element>
   <element>
      <efficiency>27.9</efficiency>
      <sales>8213000</sales>
      <year>1992</year>
   </element>
   <element>
      <efficiency>28.4</efficiency>
      <sales>8518000</sales>
      <year>1993</year>
   </element>
   <element>
      <efficiency>28.3</efficiency>
      <sales>8991000</sales>
      <year>1994</year>
   </element>
   <element>
      <efficiency>28.6</efficiency>
      <sales>8620000</sales>
      <year>1995</year>
   </element>
   <element>
      <efficiency>28.5</efficiency>
      <sales>8479000</sales>
      <year>1996</year>
   </element>
   <element>
      <efficiency>28.7</efficiency>
      <sales>8217000</sales>
      <year>1997</year>
   </element>
   <element>
      <efficiency>28.8</efficiency>
      <sales>8085000</sales>
      <year>1998</year>
   </element>
   <element>
      <efficiency>28.3</efficiency>
      <sales>8638000</sales>
      <year>1999</year>
   </element>
   <element>
      <efficiency>28.5</efficiency>
      <sales>8778000</sales>
      <year>2000</year>
   </element>
   <element>
      <efficiency>28.8</efficiency>
      <sales>8352000</sales>
      <year>2001</year>
   </element>
   <element>
      <efficiency>29</efficiency>
      <sales>8042000</sales>
      <year>2002</year>
   </element>
   <element>
      <efficiency>29.5</efficiency>
      <sales>7556000</sales>
      <year>2003</year>
   </element>
   <element>
      <efficiency>29.5</efficiency>
      <sales>7483000</sales>
      <year>2004</year>
   </element>
   <element>
      <efficiency>30.3</efficiency>
      <sales>7660000</sales>
      <year>2005</year>
   </element>
   <element>
      <efficiency>30.1</efficiency>
      <sales>7762000</sales>
      <year>2006</year>
   </element>
   <element>
      <efficiency>31.2</efficiency>
      <sales>7562000</sales>
      <year>2007</year>
   </element>
   <element>
      <efficiency>31.5</efficiency>
      <sales>6769000</sales>
      <year>2008</year>
   </element>
   <element>
      <efficiency>32.9</efficiency>
      <sales>5402000</sales>
      <year>2009</year>
   </element>
   <element>
      <efficiency>33.9</efficiency>
      <sales>5636000</sales>
      <year>2010</year>
   </element>
   <element>
      <efficiency>33.1</efficiency>
      <sales>6093000</sales>
      <year>2011</year>
   </element>
   <element>
      <efficiency>35.3</efficiency>
      <sales>7245000</sales>
      <year>2012</year>
   </element>
   <element>
      <efficiency>36.4</efficiency>
      <sales>7586000</sales>
      <year>2013</year>
   </element>
   <element>
      <efficiency>36.5</efficiency>
      <sales>7708000</sales>
      <year>2014</year>
   </element>
   <element>
      <efficiency>37.2</efficiency>
      <sales>7517000</sales>
      <year>2015</year>
   </element>
   <element>
      <efficiency>37.7</efficiency>
      <sales>6873000</sales>
      <year>2016</year>
   </element>
   <element>
      <efficiency>39.4</efficiency>
      <sales>6081000</sales>
      <year>2017</year>
   </element>
</root>
    

To query this data, update App.js and change the useEffect hook to the following:

      React.useEffect(() => {
    d3.xml("/chart-data.xml").then((d) => {
      const chartData = [];
      for (const element of d.children[0].children) {
        chartData.push({
          efficiency: element.children[0].textContent,
          sales: element.children[1].textContent,
          year: element.children[2].textContent
        })
      }
      setData(chartData);
      setLoading(false);
    });
    return () => undefined;
  }, []);
    

Notice that we have changed the URL to /chart-data.xml and the function call to d3.xml. Further, there is some extra code required to parse the XML data. This style of parsing code is error prone and requires some trial and error to get it right. It is better to retrieve your data in JSON or CSV format, since it is easier to work with from JavaScript.

Conclusion

Binding a chart from a remote data source is important for making your website visually appealing and dynamic. You have learned how to work with JSON, CSV, and XML formats. As a next step, you may want to learn more about the Fetch API to perform more advanced interactions, such as passing custom headers and error handling.