React with D3

by ramnathv

HTML

<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
<script src="//fb.me/react-with-addons-0.14.0.js"></script>
<script src="//fb.me/react-dom-0.14.0.js"></script>
<script src="//d3js.org/d3.v3.min.js"></script>
<div id="mount"></div>

CSS

#mount{margin-top: 30px;}

Babel + JSX

const Page = (props) => {
  return (
    <div className='container-fluid'>
      <div className='row'>
        <div className='col-xs-12 col-md-6'>
          <Panel heading="D3 with React">
            {props.children}
          </Panel>
        </div>
      </div>
    </div>
  )
}

const Panel = (props) => {
  return (
   <div className='panel panel-default'>
     <div className="panel-heading">{props.heading}</div>
     <div className='panel-body'>{props.children}</div>
   </div>
  )
}

const Svg = (props) => {
  return (
    <svg width={props.width} height={props.height}>
      <g transform="translate(40, 40)">
        {props.children}
      </g>
    </svg>
  )
}

const Button = (props) => {
  return(
    <button className="btn btn-primary btn-sm" {...props}>
      Update
    </button>
  )
}

const makeData = (N) => {
  return d3.range(N).map((d, i) => {
    return(
     {x: Math.random(), y: Math.random(), r: Math.random()}
    )
  })
}

const computeAttrs = (props) => {
  let S = {
    x: d3.scale.linear().range([0, props.width]),
    y: d3.scale.linear().range([props.height, 0]),
    r: d3.scale.sqrt().range([1, 8])
  }
  let A = {
    x: (d) => d.x,
    y: (d) => d.y,
    r: (d) => d.r
  }
  return({
   cx: (d) => S.x(A.x(d)), 
   cy: (d) => S.y(A.y(d)),
   r:  (d) => S.r(A.r(d)),
   fill: "steelblue"
  })
}


const Circles1 = React.createClass({
  render(){
    let SA = computeAttrs(this.props)
    let circles = this.props.data.map((d, i) => {
      return(
        <circle 
          cx={SA.cx(d)} 
          cy={SA.cy(d)} 
           r={SA.r(d)} key={i}
           fill={SA.fill}
        />
      )
    })
    return <g ref='points'>{circles}</g>
  }
})

const Circles2 = React.createClass({
  drawCircles(){
    let SA = computeAttrs(this.props)
    let el = d3.select(this.refs.points)
    let circles = el.selectAll('circle').data(this.props.data)
    circles.enter().append('circle').attr("r", 0)
    circles.transition().attr(SA)
    circles.exit().remove()
...