About using d3-react-squared — an Example

Chris Roth
Nov 21, 2015 · 7 min read

(tl;dr: see below for the explanations or check the live-version)

This ‘short’ article is meant to give an idea on how we use d3-react-squared in reactjs, to link data, events, charts, elements — in order to create a rich user experience.

IMPORTANT NOTE: the charts and the whole app are just an example, and as such not particularly useful. It was constructed to highlight a few basic ideas and features of the library. In a real project, we expect you to write your own charts and components, we just provide the/a glue to link them up.

What is d3-react-squared? Why yet another library?

Many smart people have invested a lot of time & effort into finding ways to pair react.js and d3.js (or any other charting library — or charts in react directly).

In my personal opinion, there is obviously no perfect way, i.e. a way that is optimal in all use cases. Depending on your skills, your background, your project, you might and will require a different approach. Maybe you need to keep the charts in d3 (so that your experienced designers don’t have to bother about react) or you go all-in on react, to make maximum use of the VirtualDOM and restrict the use of d3 to calculations.

So, which tool takes care of the DOM manipulations, of transitions, of creating/modifing elements, calculations, …?

So, many people have written about this subject, and to gather these ideas, I compiled a short list of some contributions, see here (please message me if you have more to add!).

So do we need another library? Maybe not.

But in our own projects, we were missing a direct way to set up charts (or any component, like a form or an inline svg element (as a ‘react chart’)) so that these components can communicate easily and share information (e.g. events & data!) to create a rich dashboard (or anything).

(big thanks here to Peter Beshai for the inspiration based on his linked charts repo, using reflux)

So what is d3-react-squared?

  • A system to share events & data
  • easily load your own (d3) charts (very slight modifications might be needed)
  • charts are reusable

And what it is NOT:

  • A library of standard charts (such as c3.js, nvd3, …)
  • A data-management tool
  • A yellow submarine or unicorn

Well, I got to learn that most people appreciate a full example to see what is actually going on, so let’s get started.

A full example

(find a live version here and the code here)

Setup

In this example, we will use the following:

How do we present it:

Prerequisites

We are using some libraries in our code that you are probably not familiar with. You do not need to understand all the details, obviously. It certainly helps if you have an understanding of redux, container/component (smart/dumb), to have an idea where the data & the actions are coming from.

From now on, we shall just assume that the data is there, ready.

Component 1: Filter

We added a quick filter to show you the interaction (changing data). It is essentially a form that fires redux actions, which in turn ‘modify’ the data displayed in the charts.

Component 2: Charts

In this example, I am using the exemplary basic bar charts that are included in the library. This charts are plain, simple and supposed to be a starting point. In a real project, you would supply your own charts.

Important note: in a real-life project, you would spend a lot of time and effort on setting up a smart way to handle data, depending on the filters and requirements you are facing. In our example, we kept the reducers simple (to make it accessible for people who don’t want to reason about redux) and did some data modification in the chart components (here).

In this tutorial, we will not look into writing your own charts, if you need help (or would love such a tutorial), please contact me (Chris Roth) or check out the resources in the examples.

To be sure, again: The bar, pie and line charts included in the d3-react-squared library are mere examples on how to set up charts so that they work with the library. On how to set up custom charts, please consult the documentation page or use this snippet:

<Chart 
chartType="custom"
chartModule=myChartModule
data={dataInTheFormatYouNeedItToBe}
params={paramsYouWantToPassToYourChart}
paddingBottom="x%"/>

So, in our simple example, we have two relevant files:

Let’s look at the first one.

First we make sure to load the module:

import DR2 from 'd3-react-squared';

(using any name we like) and then we add the chart in the render:

<DR2
data={myDataRaw}
highlightEmit={['nameLength']}
highlightListen={['nameLength']}
params={
{labelSize: 2}
}
/>

And this is it.

Note that we first had to prepare the data (myDataRaw). To coordinate the chart events, we add nameLength as highlight-Group. What does that mean? If this chart fires an event, the event with ‘nameLength’ tag will be forwarded to other components (charts and wrapped components), and those listening to corresponding tag will react. Other components will disregard the event.

Why? How? As you can see in the example, if we mouseover over a bar chart, only the one displaying the corresponding information will interact too, the other one will remain as it is (disregarding the event).

The second chart component will work just likewise.

For more information, please see the documentation page or check the source.

Component 3: Wrapped Component

As mentioned earlier, you can wrap any component, so that it can access the d3-react-squared event system (and thus: fire and receive events). For that we added wrappedComponent.js.

There are a few things worth mentioning here:

  1. We have an inline svg element (two rects) that displays data directly. Obviously, you can also link mouseevent of the chart to actions. Note how the chart reacts to filters.
  2. We have 5 yellow elements. The first two fire an event to the d3-react-squared system (mouseover on a specific element). One uses the “nameLength” tag for the event, the other the “perLetter”. Note that you could also send events to several tags (and, likewise, receive). Or to make it even more complicated: you can also send a custom event to any number of tags.
  3. Yellow element 3, 4 & 5 then fire redux actions, with the effect of filtering the data. Note how the charts react, also the inline chart above (and the filter buttons).
  4. Finally, the last line shows a log when the last event in the d3-react-squared system happened. In this example, this is not particularly helpful, but it shows that the wrapped component also updates on an event triggered in the charts (so you can do something useful here).

To wrap it up: this component reacts & sends to the redux-data system, and it reacts & sends to the d3-react-squared event system.

And how did we set it up? Check out this folder.

We are using, as mentioned above, a container/component set up, so we have 3 files:

  1. a container (smart), to link to the redux-data
  2. a component (dumb), which you could bypass in this instance, but we want to be verbose
  3. the real (very dumb) component, that relies on the redux-data & actions and the d3-event system to be present

So in the 2nd one, we have to make sure we import d3-react-squared & the wrapped component

import DR2 from ‘d3-react-squared’;
import WrappedComponent from ‘./wrappedComponent’;

And then, we just render it, passing on the other props (for redux!)

render() { 
return (
<DR2
component={WrappedComponent}
{…this.props} />
);
}

That’s it, essentially.

For instance, in the 3rd file then, we set up a small method to fire d3-react-squared events, like so:

sendEvent(id, grp, event) { 
const {setEvent} = this.props;
const eventObj = { data: {id}, event, eventGroup: grp, };
setEvent(eventObj);
}

(remember, the setEvent function is passed down as a prop, as we wrap the component)

And alternatively, redux actions are available as props (and if you use containers with bindActionCreators, they are already bound to the dispatch function).

What’s next?

You can find more information on the documentation page or, obvisouly, directly in the source.

Please note that we wrote an additional loader for c3js charts, as can be found here (d3-react-squared-c3-loader) (documentation is lacking, as of now, please check out the examples in the repo).

We are using d3-react-squared in production and wrote a few (d3-)charts & components using this setup.

We hope this library is helpful and are very grateful for any feedback & contributions.

We are currently thinking about investing time in more loaders and not include more charts in the core library.

Why?

  1. Keep things lightweight
  2. There are already plenty of chart libraries out there. Maybe we could tap their ideas by just writing a loader (like c3)?
  3. d3-react-squared was designed to load custom chart modules of any form (components or chart-modules, such as the exemplary bar chart). Thus, people can develop their own charts and publish them as modules, that depend on d3-react-squared (and, obviously, open-source the modules as standalone)

By the way: we designed the chart modules (like the bar chart) so that they do not depend on react. Meaning: if you would like to reuse the charts, it should be pretty straight-forward (we are not really experts in other frameworks, but it does work in vanilla ES2015, if you set up a good lifecycle system to trigger the data-updates).

Plans?

  1. Make things more stable, clean API, clean documentation
  2. More loaders
  3. Some basic charts (contributions? Yes please!). Be aware: we do not want to create yet another all-purpose, fully featured charting library — but a few nice basic charts as stand alone modules would be cool (see 2. & 3. above)

So if you have some feedback, ideas, contributions…, please contact us (Chris Roth)

Thanks!

Chris Roth

Written by

CTO @ ambrite (ambrite.ch)

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade