D3.js integration into React components
The challenge of integrating D3.js with React is that React and D3 both control the DOM. The entire select/enter/exit/update D3 pattern is in direct conflict with React and its virtual DOM strategy.
The Black-box technique
The solution implemented in LODEX is to wrap the D3 code in a component that will be rendered and handled by React. To do this we use React to render a SVG (our blackbox) and use D3 to fill it on React events.
This method allows us to create exactly what we want as D3 element and we have the benefit to be able to use the same kind of code as the many examples available on the web.
To do this correctly, we have to be careful about some points due to the React and D3 logics.
Base of the component
Our component must render a blackbox for D3 so we will put a SVG during the render() event:
render() {
const { width, height, margin } = this.state;
return (
<div id="divContainer"
ref={this.divContainer}
style={styles.divContainer}>
<svg id="svgContainer"
ref={this.svgContainer}
width={width}
height={height}>
</svg>
</div>
);
}
We define some methods to append and remove D3 elements to this SVG container. For
example we can create two main methods setChart()
and removeChart()
which are the
methods to append all the chart to the svgContainer
and to remove it.
We want the chart to have the capacity to update its size (e.g.: the user resizes the
window so the charts have to adapt itself to the new size). To do so we define a method
updateDimensions()
which remove and redraw the chart at the right size.
For example:
updateDimensions() {
this.removeGraph();
this.setGraph();
}
We can have other methods which will be called from those main methods. For example
a function setAxisScale()
which will be called from setChart()
.
React events
When we have these main methods we want to call it at the right time. To do this properly we use React events to create, remove and resize the chart.
-
componentDidUpdate()
is the main entry point to append the chart to our black box, that's in this event that we will callsetChart()
method because our component will already have all its datas updated like the input datas for the chart and other required informations. -
componentWillUpdate()
is the place where we remove the chart by callingremoveChart()
, like so the we will correctly update the chart when an update appears, throught thoses update events. -
componentDidMount()
is useful to setup the chart at the begin of the component lifecycle throughtsetChart()
and we will bind our previous methodupdateDimensions()
to resize like so :
window.addEventListener('resize', this.updateDimensions.bind(this))
componentWillUnmount()
will allow us to remove the chart properly at the end of the component lifecycle usingremoveChart()
and to remove the resize event binding like so :
window.removeEventListener('resize',this.updateDimensions.bind(this))