I'm wondering what's the best practice for accessing the DOM elements inside my render function from the same component. Note that I will be rendering this component multiple times on a page.
e.g.
var TodoItem = React.createClass({
...
render:function(){
function oneSecLater(){
setTimeout(function(){
//select the current className? this doesn't work, but it gives you an idea what I want.
document.getElementsByClassName('name').style.backgroundColor = "red";
)}, 1000);
}
return(
<div className='name'>{this.oneSecLater}</div>
)
})
I'm wondering what's the best practice for accessing the DOM elements inside my render function from the same component. Note that I will be rendering this component multiple times on a page.
e.g.
var TodoItem = React.createClass({
...
render:function(){
function oneSecLater(){
setTimeout(function(){
//select the current className? this doesn't work, but it gives you an idea what I want.
document.getElementsByClassName('name').style.backgroundColor = "red";
)}, 1000);
}
return(
<div className='name'>{this.oneSecLater}</div>
)
})
Share
Improve this question
edited Jan 11, 2022 at 7:04
Yilmaz
49k18 gold badges212 silver badges267 bronze badges
asked Feb 15, 2017 at 6:29
wonghenrywonghenry
6892 gold badges7 silver badges18 bronze badges
6 Answers
Reset to default 26You can use ReactDOM.findDOMNode(this)
to access the underlying DOM node. But accessing the DOM node and manipulating like you do is against the React style of programming. It's better to use a state variable and called the setState
method to re-render the DOM.
Here, no need to use setTimeout. There are lifecycle methods for component, of which componentDidMount
is called after the render. So, you can get the reference to your div in the method.
var TodoItem = React.createClass({
...
componentDidMount: function () {
if(this.myDiv) {
this.myDiv.style.backgroundColor = "red";
}
}
render:function(){
return(
<div className='name' ref = {c => this.myDiv = c}></div>
);
});
You can make use of ref callback
to access the dom element in react, which is what React Docs recommend to follow
and do that in the componentDidMount
lifecycle function as refs won't be accessible before the DOM is created
var TodoItem = React.createClass({
...
componentDidMount() {
setTimeout(function(){
this.myDiv.style.backgroundColor = "red";
)}, 1000);
}
render:function(){
return(
<div className='name' ref={(ele) => this.myDiv = ele}></div>
)
})
DOCS
You should avoid accessing DOM element because the whole point of react is putting abstraction over dom. React keeps representation of DOM in memory which is referred as VirtualDom. Working with VirtualDom will make unit testing your application is easier.If you really know what you are doing, here is how to do it:
componentDidMount(){
const name=this.name.current.style() //current will return the actual DOM
element
}
name=React.createRef() //create a ref object
<div ref={this.name} className="anything" /> //your classname does not need to be named as "name". You access the element via the "ref" attribute not the classname.
In ComponentDidMount, when your component is mounted its style change will be applied.
Just came across this after trying to do form validation before opening a stripe checkout modal with React 14.
I would like to note that you're not actually accessing a DOM Element with references. You're simply accessing the React Component Object. Shown here:
The top one is calling ref.ticketForm
, the bottom is showing document.getElementById('ticketform')
.
The reason I needed to do this was the following:
<Button color="success" size="lg" type="button" onClick={(e) => {
const ticketForm = document.getElementById('ticketForm');
const isValid = ticketForm.reportValidity();
if (!isValid) e.stopPropagation();
}}>Buy Tickets</Button>
reportValidity()
is a DOM Element method: https://developer.mozilla.org/en-US/docs/Web/API/HTMLFormElement/reportValidity
Referencing this issue, this person showed this method being used on a reference object, which naturally isn't correct: https://github.com/azmenak/react-stripe-checkout/issues/121#issuecomment-431635855
Hopefully this clears up that DOM Elements do not explicitly equal React Components. If you need to manipulate the DOM in any way, do it in a react way first. This is an edge case where I would rather rely on form validation for a dynamic form than manually doing very heavy custom validation.
here is my solution: To get a computedCss of an specific element, you need to add a ref attribute to the elemenet first.
enter image description here
render(){
<div>
<Row className="chartline2">
<Col className="gutter-row" span={24}>
<div className="gutter-box lineChartWrap" id="lineChartWrap" ref="lineChartWrap">
<LineChart data={lineChartData} options={lineChartOptions} width="100%" height="300"/>
</div>
</Col>
</Row>
</div>
}
And then, in the componentDidUpdate() function, get your element's css by using window.getComputedStyle(this.refs.lineChartWrap).XXX enter image description here
componentDidUpdate(){
console.log("------- get width ---");
let ele = document.querySelector("#lineCharWrap");
console.log(this.refs.lineChartWrap);
console.log(window.getComputedStyle(this.refs.lineChartWrap).width);
}