React, how to access the DOM element in my render function from the same component

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>
        )



})

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

You 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.

Method 2

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>
    );
});

Method 3

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

Method 4

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.

Method 5

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:

enter image description 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.

Method 6

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);
    }


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x