Any modification to state
/ props
/ context
will trigger a re-render to VirtualDOM
Changes will be flushed to the DOM
No DOM direct access
el.appendChild(childNode)
el.innerHTML = 'foo'
Event delegation
No DOM direct access
onClick={handler}
≠onclick="javascript:alert('toto')"
el.addEventListener('click', handler, false)
const valueline = d3.line()
.x(d => x(d.date))
.y(d => y(d.price));
const svg = d3.select('body').append('svg');
svg.append('path')
.data([data])
.attr('d', valueline);
const chartProps = {
data,
maxX,
maxY,
minX,
minY,
width,
height,
margin
}
<SomeChart {...chartProps} />
import { select } from 'd3-selection';
// ...
render() {
return (
<svg ref={(node) => this.rootNode = select(node)}></svg>
);
}
componentDidMount
componentWillReceiveProps
shouldComponentUpdate
componentWillUpdate
componentDidUpdate
render() {
const rootNode = ReactFauxDOM.createElement('svg');
// ... some d3-like code
return rootNode.toReact();
}
Trick d3 with a DOM like structure that renders to React
Think of it like jsdom
with a .toReact()
method
that renders into React elements
DrawCircles = ({ data, ...props }) => {
const d3computedData = d3(data, props); // fake
return (
<svg height={d3computedData.height}
width={d3computedData.width}>
{d3computedData.circles.map((circleData, key) => <circle
key={key}
cx={circleData.x}
cy={circleData.y}
r={circleData.radius}
fill={circleData.color} />)}
</svg>
)
// or ...
return (
<svg height={d3computedData.height}
width={d3computedData.width}>
{d3computedData.circles.map((circleData, key) => <MyCircle
key={key}
{...circleData} />)}
</svg>
);
}
* You might end up creating the same kind of components as existing libraries ...