I am currently using react to create d3 visualizations. I'm a little confused about the relationship between the render
and componenetDidMount
methods (is methods the proper term?). Here is what I have (I excluded some code for simplicity):
var Chart = React.createClass({
componentDidMount: function () {
var el = this.getDOMNode();
console.log(el);
d3Chart.create(el, {
width: '500',
height: '300'
}, this.getChartState(),this.getAccessState);
},
render: function () {
return (
<div className="row pushdown">
<div className="d3-block">
<div className="Chart" />
</div>
</div>
);
}
}
On line 3, el
gets assigned this.getDOMNode();
which always points to the top level element in the render function (div "row pushdown"
). So does this.getDOMNode()
always refer to the top level element in the render function? What I'm actually trying to do is render the d3 chart within the innermost div
(.Chart
). I first tried doing this.getDOMNode().find('.Chart')
but that didn't work.
First question: I know that I shouldn't be trying to touch the real DOM here but how would I go about selecting something further down on the VirtualDOM?
Second question: I know that, given I am very new to this, am probably doing this the wrong way. Can you suggest a better method here?
Third question: I want to add a chart legend in a sibling div
of ".Chart"
. Should I be creating a new component for this? Or in my d3Chart can I use selectors to do this?
Thank you in advance for your help!
P.S. I have one side question:
I've seen people use React.render(<Chart />,document.body)
instead of using React.createElement
within that. Could somebody explain to me the difference?
Yes, getDOMNode()
returns the outermost DOM element that was render
ed.
A1. I'd suggest you use a ref
attribute (documentation) which provides a reference to the DOM element for later usage:
<div ref="chart" className="Chart" />
componentDidMount: function() {
// << you can get access to the element by name as shown below
var chart = this.refs.chart;
// do what you want here ...
}
A2. While ultimately you might want to refactor your code into multiple components, there's nothing wrong with what you've created (assuming you try the ref
option mentioned above).
A3. As the legend would represent a very different piece of functionality (and isolated), creating a distinct component would be typical React. You might still have a Chart
component that contains both the actual chart visualization but also has another component which displays a legend. It's a nice separation of concerns. But, you could also consider a Flux model where each component listens for changes and renders its visuals completely independently. If they work tightly together, a Flux model may not make as much sense.
Side: Using JSX, you might see:
React.render(<App />, document.body)
That would just render the App
into the document body contents.
That is equivalent to precompiled JSX:
React.render(React.createElement(App, null), document.body);
Just a note...as of v0.13. componentDidMount()
may not yet have this.refs
available. From the changelog:
ref
resolution order has changed slightly such that a ref to a component is available immediately after its componentDidMount
method is called; this change should be observable only if your component calls a parent component's callback within your componentDidMount
, which is an anti-pattern and should be avoided regardless
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With