How to access a DOM element in React? What is the equilvalent of document.getElementById() in React

JavascriptReactjsGetelementbyid

Javascript Problem Overview


How do I select certain bars in react.js?

This is my code:

var Progressbar = React.createClass({
    getInitialState: function () {
        return { completed: this.props.completed };
    },
    addPrecent: function (value) {
        this.props.completed += value;
        this.setState({ completed: this.props.completed });
    },

    render: function () {

        var completed = this.props.completed;
        if (completed < 0) { completed = 0 };


        return (...);
    }

I want to use this React component:

var App = React.createClass({
    getInitialState: function () {

        return { baction: 'Progress1' };
    },
    handleChange: function (e) {
        var value = e.target.value;
        console.log(value);
        this.setState({ baction: value });
    },
    handleClick10: function (e) {
        console.log('You clicked: ', this.state.baction);
        document.getElementById(this.state.baction).addPrecent(10);
    },
    render: function () {
        return (
            <div class="center">Progress Bars Demo
            <Progressbar completed={25} id="Progress1" />
                <h2 class="center"></h2>
                <Progressbar completed={50} id="Progress2" />
                <h2 class="center"></h2>
                <Progressbar completed={75} id="Progress3" />
                <h2 class="center"></h2>
                <span>
                    <select name='selectbar' id='selectbar' value={this.state.baction} onChange={this.handleChange}>
                        <option value="Progress1">#Progress1</option>
                        <option value="Progress2">#Progress2</option>
                        <option value="Progress3">#Progress3</option>
                    </select>
                    <input type="button" onClick={this.handleClick10} value="+10" />
                    <button>+25</button>
                    <button>-10</button>
                    <button>-25</button>
                </span>
            </div>
        )
    }
});

I want to execute the handleClick10 function and perform the operation for my selected progressbar. But the result I get is:

 You clicked:  Progress1
 TypeError: document.getElementById(...) is null

How do I select the certain Element in react.js?

Javascript Solutions


Solution 1 - Javascript

You can do that by specifying the ref

EDIT: In react v16.8.0 with function component, you can define a ref with useRef. Note that when you specify a ref on a function component, you need to use React.forwardRef on it to forward the ref to the DOM element of use useImperativeHandle to to expose certain functions from within the function component

Ex:

const Child1 = React.forwardRef((props, ref) => {
    return <div ref={ref}>Child1</div> 
});

const Child2 = React.forwardRef((props, ref) => {
    const handleClick= () =>{};
    useImperativeHandle(ref,() => ({
       handleClick
    }))
    return <div>Child2</div> 
});
const App = () => {
    const child1 = useRef(null);
    const child2 = useRef(null);

    return (
        <>
           <Child1 ref={child1} />
           <Child1 ref={child1} />
        </>
    )
}

EDIT:

In React 16.3+, use React.createRef() to create your ref:

class MyComponent extends React.Component {
  constructor(props) {
    super(props);
    this.myRef = React.createRef();
  }
  render() {
    return <div ref={this.myRef} />;
  }
}

In order to access the element, use:

const node = this.myRef.current;

DOC for using React.createRef()


EDIT

However facebook advises against it because string refs have some issues, are considered legacy, and are likely to be removed in one of the future releases.

From the docs:

> Legacy API: String Refs > > If you worked with React before, you might be > familiar with an older API where the ref attribute is a string, like > "textInput", and the DOM node is accessed as this.refs.textInput. 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.

A recommended way for React 16.2 and earlier is to use the callback pattern:

<Progressbar completed={25} id="Progress1" ref={(input) => {this.Progress[0] = input }}/>

<h2 class="center"></h2>

<Progressbar completed={50} id="Progress2" ref={(input) => {this.Progress[1] = input }}/>

  <h2 class="center"></h2>

<Progressbar completed={75} id="Progress3" ref={(input) => {this.Progress[2] = input }}/>

DOC for using callback


Even older versions of react defined refs using string like below

<Progressbar completed={25} id="Progress1" ref="Progress1"/>

    <h2 class="center"></h2>

    <Progressbar completed={50} id="Progress2" ref="Progress2"/>

      <h2 class="center"></h2>

    <Progressbar completed={75} id="Progress3" ref="Progress3"/>

In order to get the element just do

var object = this.refs.Progress1;

Remember to use this inside an arrow function block like:

print = () => {
  var object = this.refs.Progress1;  
}

and so on...

Solution 2 - Javascript

For getting the element in react you need to use ref and inside the function you can use the ReactDOM.findDOMNode method.

But what I like to do more is to call the ref right inside the event

<input type="text" ref={ref => this.myTextInput = ref} />

This is some good link to help you figure out.

Solution 3 - Javascript

With newer versions of React you can use and manipulate the DOM via hooks like this:

import React, { useEffect, useRef } from "react";

const MyComponent = () => {
  const myContainer = useRef(null);
  
  useEffect(() => {
    console.log("myContainer..", myContainer.current);
  });

  return (
    <>
      <h1>Ref with react</h1>
      <div ref={myContainer}>I can use the DOM with react ref</div>
    </>
  );
};

export default MyComponent;

Whenever you want to access your DOM element just use myContainer

Solution 4 - Javascript

You can replace

document.getElementById(this.state.baction).addPrecent(10);

with

this.refs[this.state.baction].addPrecent(10);


  <Progressbar completed={25} ref="Progress1" id="Progress1"/>

Solution 5 - Javascript

Disclaimer: While the top answer is probably a better solution, as a beginner it's a lot to take in when all you want is something very simple. This is intended as a more direct answer to your original question "How can I select certain elements in React"

I think the confusion in your question is because you have React components which you are being passed the id "Progress1", "Progress2" etc. I believe this is not setting the html attribute 'id', but the React component property. e.g.

class ProgressBar extends React.Component {
    constructor(props) {
        super(props)
        this.state = {
            id: this.props.id    <--- ID set from <ProgressBar id="Progress1"/>
        }
    }        
}

As mentioned in some of the answers above you absolutely can use document.querySelector inside of your React app, but you have to be clear that it is selecting the html output of your components' render methods. So assuming your render output looks like this:

render () {
    const id = this.state.id
    return (<div id={"progress-bar-" + id}></div>)
}

Then you can elsewhere do a normal javascript querySelector call like this:

let element = document.querySelector('#progress-bar-Progress1')

Solution 6 - Javascript

The equivalent of document.getElementById() in React is document.querySelector().

Solution 7 - Javascript

Since React uses JSX code to create an HTML we cannot refer dom using regulation methods like documment.querySelector or getElementById.

Instead we can use React ref system to access and manipulate Dom as shown in below example:

constructor(props){

	super(props);
	this.imageRef = React.createRef(); // create react ref
}

componentDidMount(){

	**console.log(this.imageRef)** // acessing the attributes of img tag when dom loads
}


render = (props) => {

const {urls,description} = this.props.image;
	return (
			
			<img
	 		 **ref = {this.imageRef} // assign the ref of img tag here**
			 src = {urls.regular} 
			 alt = {description}
			 />
			 
		);

}

}

Solution 8 - Javascript

In my case, I wasn't able to use ref because elements were somewhere between many child components and I have to access them by class and id instead of ref. So, trying with useEffect hook didn't work as it can't find the element:

useEffect(() => {
  const el1 = document.querySelector('.el1')
  const el2 = document.querySelector('.el2')
}, [])

The element is undefined because when it is mounted the children components also doesn't mounted before this parent component.

So, what I did is to use timeout:

useEffect(() => {
  const timer = setTimeout(() => {
    const el1 = document.querySelector('.el1')
    const el2 = document.querySelector('.el2')
  },500)
  return () => {
    clearTimeout(timer)
  }
}, [])

Now, it worked fine. It found the DOM and I was able to manipulate with them. Hope, this helps someone!

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionuser504909View Question on Stackoverflow
Solution 1 - JavascriptShubham KhatriView Answer on Stackoverflow
Solution 2 - JavascriptEQuimperView Answer on Stackoverflow
Solution 3 - JavascriptChristianView Answer on Stackoverflow
Solution 4 - JavascriptPiyush.kapoorView Answer on Stackoverflow
Solution 5 - JavascriptEdward SpencerView Answer on Stackoverflow
Solution 6 - JavascriptAlex RView Answer on Stackoverflow
Solution 7 - JavascriptNikhil KamaniView Answer on Stackoverflow
Solution 8 - JavascriptBhojendra RauniyarView Answer on Stackoverflow