React D3 Multiple Approaches
HTML
<script src="//fb.me/react-with-addons-0.14.0.js"></script>
<script src="//fb.me/react-dom-0.14.0.js"></script>
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
<script src="//cdnjs.cloudflare.com/ajax/libs/react-bootstrap/0.28.1/react-bootstrap.min.js"></script>
<div class="container-fluid" id="app">
<div class="row">
<div class="col-md-6 col-xs-12">
<div class="panel panel-default">
<div class="panel-heading">
D3 + React
</div>
<div class="panel-body">
<div id="chart"></div>
<div id="main" />
</div>
</div>
</div>
</div>
</div>
CSS
#app{margin-top: 30px;}
CoffeeScript
R = React.DOM
Rc = React.createElement
Rb = ReactBootstrap
var width = 960;
var height = 500;
var force = d3.layout.force()
.charge(-300)
.linkDistance(50)
.size([width, height]);
// *****************************************************
// ** d3 functions to manipulate attributes
// *****************************************************
var enterNode = (selection) => {
selection.classed('node', true);
selection.append('circle')
.attr("r", (d) => d.size)
.call(force.drag);
selection.append('text')
.attr("x", (d) => d.size + 5)
.attr("dy", ".35em")
.text((d) => d.key);
};
var updateNode = (selection) => {
selection.attr("transform", (d) => "translate(" + d.x + "," + d.y + ")");
};
var enterLink = (selection) => {
selection.classed('link', true)
.attr("stroke-width", (d) => d.size);
};
var updateLink = (selection) => {
selection.attr("x1", (d) => d.source.x)
.attr("y1", (d) => d.source.y)
.attr("x2", (d) => d.target.x)
.attr("y2", (d) => d.target.y);
};
var updateGraph = (selection) => {
selection.selectAll('.node')
.call(updateNode);
selection.selectAll('.link')
.call(updateLink);
};
// *****************************************************
// ** Graph and App components
// *****************************************************
var Graph = React.createClass({
componentDidMount() {
this.d3Graph = d3.select(ReactDOM.findDOMNode(this.refs.graph));
force.on('tick', () => {
// after force calculation starts, call updateGraph
// which uses d3 to manipulate the attributes,
// and React doesn't have to go through lifecycle on each tick
this.d3Graph.call(updateGraph);
});
},
shouldComponentUpdate(nextProps) {
this.d3Graph = d3.select(ReactDOM.findDOMNode(this.refs.graph));
var d3Nodes = this.d3Graph.selectAll('.node')
.data(nextProps.nodes, (node) => node.key);
d3Nodes.enter().append('g').call(enterNode);
d3Nodes.exit().remove();
...