I’m tying to position a circle in the middle of the component’s root DOM element:
var App = React.createClass({
render: function() {
return <svg ref="svg">
<circle r="9" cx={this.centerX()} cy="15"/>
</svg>;
},
centerX: function() {
var svg = this.refs.svg.getDOMNode();
return svg.offsetLeft + Math.round(svg.offsetWidth / 2);
}
});
http://jsfiddle.net/NV/94tCQ/
Chicken-and-egg problem takes place here: this.refs
is undefined on the first render. What’s the best way to solve this it? I would prefer not to reference external DOM nodes (such as document.body
).
You can create a ref by calling React. createRef() and attaching a React element to it using the ref attribute on the element. We can “refer” to the node of the ref created in the render method with access to the current attribute of the ref. From the example above, that would be this.
String refs force React to keep track of currently executing component. This is problematic because it makes react module stateful, and thus causes weird errors when react module is duplicated in the bundle.
We advise against it because string refs have some issues, are considered legacy, and are likely to be removed in one of the future releases. If you're currently using this. refs. textInput to access refs, we recommend the callback pattern instead.
It's not that refs
isn't defined, it's that you're trying to access the DOM at the same time you are trying to generate it. this.refs.svg.getDOMNode
will not return anything because the component has no real DOM representation in render
.
To keep this more React-y, I would move cx
to the component's state and update it after the element has been rendered to the DOM:
var App = React.createClass({
componentDidMount: function() {
var svg = this.refs.svg.getDOMNode();
this.setState({
cx: svg.offsetLeft + Math.round(svg.offsetWidth / 2)
});
},
getInitialState: {
return {
cx: 0
};
},
render: function() {
return (
<svg ref="svg">
<circle r="9" cx={this.state.cx} cy="15" />
</svg>
);
}
});
A hacky way to solve this issue is to return a dummy value when it is not inserted in the DOM yet and when it is (using componentDidMount) then re-draw the element.
centerX: function() {
if (!this.refs || !this.refs.svg) {
return 0;
}
var svg = this.refs.svg.getDOMNode();
return svg.offsetLeft + Math.round(svg.offsetWidth / 2);
},
componentDidMount: function() {
this.forceUpdate();
}
http://jsfiddle.net/vjeux/94tCQ/4/
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