Be the first user to complete this post

  • 0
Add to List

Render a d3js Tree as a React Component

React is very good and optimizing client side render. However, what if you need to use d3 in your project? For simple diagrams such as bar graphs etc, you can mess around with svg properties and let react handle the render for you. But what if you just need to use the expressive power of d3 but still retain the component model of React. Fortunately, there is a still a way to make these two powerful frameworks play together. The way we are going to do that is by encapsulating a function that renders a tree within a React component. The component itself only renders a blank svg node in the render function. But inside of the componentDidMount function, we invoke the d3 function that draws our data on the blank svg. NOTE: The entire source code of this project is available at github on the react-d3-tree branch of our react-webpack-setup project. If you are inclined to learn how to setup react with webpack you can checkout another article that covers the topic in detail.
Since we are going to use the react-webpack-setup project, we will be conveniently using npm and require in our front end code.

The packages

D3 is available as a package from npm, so you can add it to your project by running
npm install d3

The components

The next part of the code shows the main Page.jsx file that acts as the master component of the page. Since this is just an example, we will be creating the treeData object in this component and passing it down to the D3Tree component. js/components/index/Page.jsx
/**
 * @jsx React.DOM
 */

var React = require('react'),
    D3Tree = require('./D3Tree'),
    treeData = [
      {
        "name": "Top Level",
        "parent": "null",
        "children": [
          {
            "name": "Level 2: A",
            "parent": "Top Level",
            "children": [
              {
                "name": "Son of A",
                "parent": "Level 2: A"
              },
              {
                "name": "Daughter of A",
                "parent": "Level 2: A"
              }
            ]
          },
          {
            "name": "Level 2: B",
            "parent": "Top Level"
          }
        ]
      }
    ];

var Page = React.createClass({

    render: function() {

        return (
            <div>
                <D3Tree treeData={treeData} />
            </div>
        );

    }

});

module.exports = Page;

To actually render the tree, we will be wrap the code in Mike Bostock's example in a function renderTree but only change one line in that code and replace it with our own selector for the svg node which is passed in as the argument. js/components/index/D3Tree.jsx
/**
 * @jsx React.DOM
 */

var React = require('react'),
  d3 = require('d3');

var D3Tree = React.createClass({

  componentDidMount: function(){
    var mountNode = this.getDOMNode();

    // Render the tree usng d3 after first component mount
    renderTree(this.props.treeData, mountNode);
  },

  shouldComponentUpdate: function(nextProps, nextState){
    // Delegate rendering the tree to a d3 function on prop change
    renderTree(this.props.treeData, this.getDOMNode());

    // Do not allow react to render the component on prop change
    return false;
  },

  render: function() {

    // Render a blank svg node
    return (
      <svg></svg>
    );
  }

});


var renderTree = function(treeData, svgDomNode) {
    // Add the javascript code that renders the tree from
    // http://bl.ocks.org/d3noob/8329404
    // And replace the line that reads
    // var svg = d3.select("body").append("svg")
    // with 
    // var svg = d3.select(svgDomNode)
}

That said, you are now ready for showtime. To see the working example for yourself, download the branch - react-backbone-model from our repository and run the following commands on your terminal.
sudo npm install -g grunt-cli
npm install
npm run dev
Then open localhost:3000/index.html in your browser and you should be able to see a tree rendered using d3 and react.



Also Read:

  1. How to get the data of a node in d3
  2. Selecting a node in d3js based upon the value of its data
  3. Pass down props using React childContextTypes in a deeply nested component tree
  4. Automating Store and Action registration for multiple components using Fluxxor
  5. Using context and childContext in React