React – access a DOM element without an ID

(or any other “normal” selectors)

This is another one that’s probably very basic, but I found it hard to find information on & hard to figure out.

Basically, I had a bunch of elements that were identical as a result of an array being mapped to DOM elements. It looked a bit like this:

JavaScript
<div>
  {array.map(thing => (
    <MyComponent thing={thing}/>
  ))}
</div>

// MyComponent might return...
<div>
  <p>Blah Blah</p>
  <button>Click Me</button>
</div>

With the output being:

HTML
<div>
  <div>
    <p>Blah Blah</p>
    <button>Click Me</button>
  </div>
  <div>
    <p>Blah Blah</p>
    <button>Click Me</button>
  </div>
   <div>
    <p>Blah Blah</p>
    <button>Click Me</button>
  </div>
   <div>
    <p>Blah Blah</p>
    <button>Click Me</button>
  </div>
</div>

Say I want to scroll to the matching <p> element when the button is clicked. One very sensible way to make this work would be to simply give each <p> element a unique ID. But what if we can’t do that for some reason?

React allows us to pass a ref attribute to access a DOM node.

Using a ref might look like this:

JavaScript
// In MyComponent:
import React, {useRef} from 'react';
const MyComponent = () => {
  const myRef = useRef(null)
  
  return (
    <div>
      <p ref={myRef}>Blah Blah</p>
      <button>Click Me</button>
    </div>
  );
}
export default MyComponent;

The useRef() hook returns an object with a property called current. That property allows you to access the DOM node.

Because I now have my ref, I can manipulate the DOM using it:

JavaScript
// In MyComponent:
import React, {useRef} from 'react';
const MyComponent = () => {
  const myRef = useRef(null)
  
  // Using the ref to scroll the page so the ref element is in view.
  const scrollToText = () =>{
    myRef.current.scrollIntoView();
  } 
  
  return (
    <div>
      <p ref={myRef}>Blah Blah</p>
      <button onClick={() => scrollToText()}>Click Me</button>
    </div>
  );
}
export default MyComponent;

I’ve used this to create a DIY slider/gallery component which uses buttons to scroll between the images. In my case, I had originally tried using IDs for the slider element that needed to be scrolled – but this caused issues as soon as I had more than one slider on the page, as document.getElementById only ever returns the first element with the ID.

It’s worth noting that useRef does not cause a re-render like useState, and it’s best practice to only use refs for things that react does not expose directly – i.e. don’t try to add and remove DOM nodes using refs, there are better ways to do that in React. The React documentation has a good demo of this.

Leave a Reply

Your email address will not be published. Required fields are marked *