Transition from using D3 in React to Angular
By: Christopher Lanoue
Tags: React, Data Visualization, JavaScript, D3js, Angular

In this article, I will go over my transition from React to Angular and point out some of the nuances I found; in case you want to simply check out the code it is available on Github.

As a User Experience/Data Visualization Engineer at Kabbage I’m tasked with helping our product teams create rapid prototypes of upcoming features to present to customers using real data to better understand our customer’s needs. For this role, I am constantly building new user interfaces and data visualizations for user experience (UX) experiments. Given my background and comfort developing in React and D3, I am able to work fastest in these technologies, but since Kabbage is an Angular front-end shop many of my prototypes are not immediately useful to the front-end engineers building the end products. At this point, some may ask why I don’t simply opt for a third-party library and sure most of the time when we need a line chart or bar chart this would work well, but to differentiate ourselves and innovate in the highly competitive FinTech space we don’t want to be constrained with only the visualizations available in a third-party library.

During the holidays, I found myself with some time to explore how to build prototypes using Angular and D3 and become a better asset to our production engineering teams. This wasn’t as easy as I initially thought given the nuances of each front-end framework, but once I got over the initial learning curve it isn’t too bad and is easy to replicate across applications.

App Creation

The first thing I noticed when creating a new project with the two frameworks is that Angular comes with all the bells and whistles, which isn’t necessarily a bad thing — routing in React is not fun — but for the purpose of this example it is definitely overkill.

// React

npx create-react-app react-app // Angular

npm install -g @angular/cli

ng new angular-app

While writing the example app for this blog, I found that instead of creating new files by hand and making sure they were correctly added to app.module.ts Angular makes it easy by providing a helper CLI function for this task.

ng generate component visualization

ng generate component visualization/axes

ng generate component visualization/marker

Code Structure

I don’t know if it comes from working with React for so many years, but I’ve come to enjoy JSX and writing HTML in the same code block as my JavaScript. It came as a bit of a shock to me to be tabbing back and forth between my HTML and TypeScript while I was debugging my Angular code. With modern IDEs, it is not hard to have the two files side-by-side, but there is something I just like about having everything together in a single location.

Along the same lines, I’ve had a blast working with React Hooks over the last year or so. It’s been life changing to never have to worry about this or duplicating the same action in an update or mount block. It was, and still is, a bit of a transition to remember to always include this.variable when referring to a variable or function and working with constructor , ngOnChanges , or ngOnInit .

DOM Control

About 95% of the time I find it easier and more performant to have React or Angular control the DOM, but in two specific cases I find myself relying on D3 to control the DOM. In both of these cases, since we are using a third-party DOM library (D3), it is necessary to have a reference to the nodes we wish to change. In React, refs are the preferred way to grab the DOM element, while in Angular it is preferred to use the generic DOM API querySelector() .

Animation/transitions

Where D3 really shines and provides that WOW factor when presenting a new shiny visualization to your company is with animations or transitions. D3 provides a developer with an almost infinite array of transition possibilities: interpolating from one color to another, easing a circle from one side of the screen to the other, or even chaining transitions one after another.

One trick to using d3.transition is that you must “track” the DOM element with which you want to update and each tracker should be unique. Without proper tracking on each element, the framework will not know which element to update. A common shortcut is to use the index of the object in the array as a tracker ( data.map((d, idx) => <circle key={`marker-${idx}`}></circle>)) ), but if that array is sorted or changed in any way on future updates the elements will not transition correctly and you’ll be scratching your head.

Animating DOM Elements with tracking

After adding the correct tracking to the element array, D3 makes it easy to transition any number of styles or attributes on a DOM element. For example, in the below snippets we are starting with a radius of 7.5px on the circle and then animating the circle from its current x- and y-position to a new x- and y-position. Without specifying an easing function, D3 will linearly interpolate between the current position (0 to start) and the new position across a time period (1 second in this example).

Note that in the Angular example, the heavy lifting of the transition is coming from a TransitionDirective that does the animation behind the scenes. A big h/t to https://github.com/AlexPikalov/ngd3 for assistance with the elegant D3 transition directive.

2. Axis creation

One of my favorite features of D3 is its ability to attach a full-featured (domain, ticks, tick lines, etc.) y- and x-axis to a visualization. The caveat to this is that it was built to be used with d3.select() , so there are a few changes to make it work within React and Angular.

Conclusion

I may never be able to move as fast in Angular as I can in React when using D3, but if I build a prototype of a feature that is widely praised amongst our research participants, we will be able to get it to market much faster and have more success as a company. Plus, there are always opportunities to jump back into React when building flashy PR visualizations.