Tuesday, August 30, 2016

Building Animated Components, or How React Makes D3 Better

D3 is great. As the jQuery of the web data visualization world, it can do everything you can think of.

Many of the best data visualizations you've seen online use D3. It is a great library, and with the recent v4 update, it became more robust than ever.

Add React, and you can make D3 even better.

Just like jQuery, D3 is powerful but low level. The bigger your visualization, the harder your code becomes to work with, the more time you spend fixing bugs and pulling your hair out.

React can fix that.

You can read my book React+d3js ES6 for a deep insight, or keep reading for an overview of how to best integrate React and D3. In a practical example, we'll see how to build declarative transition-based animations.

A version of this article also exists as a D3 meetup talk on YouTube.

Is React Worth It?

OK, React is big. It adds a ton of code to your payload, and it increases your dependency footprint. It’s yet another library that you have to keep updated.

If you want to use it effectively, you'll need a build step. Something to turn JSX code into pure JavaScript.

Setting up Webpack and Babel is easy these days: just run create-react-app. It gives you JSX compilation, modern JavaScript features, linting, hot loading, and code minification for production builds. It's great.

Despite the size and tooling complexity, React is worth it, especially if you're serious about your visualization. If you're building a one-off that you’ll never have to maintain, debug, or expand, stick to pure D3. If you're building something real, I encourage you to add React to the mix.

To me, the main benefit is that React ~~forces~~ strongly encourages you to componentize your code. The other benefits are either symptoms of componentization, or made possible by it.

The main benefits of using React with your D3 code are:

  • componentization
  • easier testing & debugging
  • smart DOM redraws
  • hot loading

Componentization encourages you to build your code as a series of logical units - components. With JSX, you can use them like they were HTML elements: <Histogram />, <Piechart />, <MyFancyThingThatIMade />. We'll dive deeper into that in the next section.

Building your visualization as a series of components makes it easier to test and debug. You can focus on logical units one at a time. If a component works here, it will work over there as well. If it passes tests and looks nice, it will pass tests and look nice no matter how often you render it, no matter where you put it, and no matter who calls it. 🙌

React understands the structure of your code, so it knows how to redraw only the components that have changes. There’s no more hard work in deciding what to re-render and what to leave alone. Just change and forget. React can figure it out on its own. And yes, if you look at a profiling tool, you'll see that only the parts with changes are re-rendered.

alphabet-redraws

Using create-react-app to configure your tooling, React can utilize hot loading. Let's say you're building a visualization of 30,000 datapoints. With pure D3, you have to refresh the page for every code change. Load the dataset, parse the dataset, render the dataset, click around to reach the state you're testing … yawn.

With React -> no reload, no waiting. Just immediate changes on the page. When I first saw it in action, it felt like eating ice cream while the crescendo of 1812 Overture plays in the background. Mind = blown.

Benefits of Componentization

Components this, components that. Blah blah blah. Why should you care? Your dataviz code already works. You build it, you ship it, you make people happy.

But does the code make you happy? With components, it can. Components make your life easier because they make your code:

  • declarative
  • reusable
  • understandable
  • organized

It's okay if that sounds like buzzword soup. Let me show you.

For instance, declarative code is the kind of code where you say what you want, not how you want it. Ever written HTML or CSS? You know how to write declarative code! Congratz!

React uses JSX to make your JavaScript look like HTML. But don't worry, it all compiles to pure JavaScript behind the scenes.

Try to guess what this code does:

render() {
  // ...
  return (
      <g transform={translate}>
          <Histogram data={this.props.data}
                     value={(d) => d.base_salary}
                     x={0}
                     y={0}
                     width={400}
                     height={200}
                     title="All" />
          <Histogram data={engineerData}
                     value={(d) => d.base_salary}
                     x={450}
                     y={0}
                     width={400}
                     height={200}
                     title="Engineer" />
          <Histogram data={programmerData}
                     value={(d) => d.base_salary}
                     x={0}
                     y={220}
                     width={400}
                     height={200}
                     title="Programmer"/>
          <Histogram data={developerData}
                     value={(d) => d.base_salary}
                     x={450}
                     y={220}
                     width={400}
                     height={200}
                     title="Developer" />
      </g>
  )
}

If you guessed "Renders four histograms", you were right. Hooray.

After you create a Histogram component, you can use it like it was a normal piece of HTML. A histogram shows up anywhere you put <Histogram /> with the right parameters.

In this case, the parameters are x and y coordinates, width and height sizing, the title, some data, and a value accessor. They can be anything your component needs.

Parameters look like HTML attributes, but can take any JavaScript object, even functions. It's like HTML on steroids.

With some boilerplate and the right dataset, that code above gives you a picture like this. A comparison of salary distributions for different types of people who write software.

4 histograms of salary distributions

Look at the code again. Notice how reusable components are? It's like <Histogram /> was a function that created a histogram. Behind the scenes it does compile into a function call - (new Histogram()).render(), or something similar. Histogram becomes a class, and you call an instance's render function every time you use <Histogram />.

React components should follow the principles of good functional programming. No side effects, statelessness, idempotency, comparability. Unless you really, really want to break the rules.

Unlike JavaScript functions where following these principles requires deliberate effort, React makes it hard not to code that way. That's a win when you work in a team.

Continue reading %Building Animated Components, or How React Makes D3 Better%


by Swizec Teller via SitePoint

No comments:

Post a Comment