How to expose and access a specific DOM element in ReactJS

How to expose and access a specific DOM element in ReactJS

In this article, we are going to use the following example of creating a ReactJS component of a library that exists already, like a 360 degrees image viewer. There are plenty of libraries in JavaScript that help you to implement such a thing, however, most of them require as a parameter of initialization a DOM element e.g:

let options = {};
let domElement = document.getElementById("item");

ThirdParty360ViewerLibrary.initialize(domElement, options);

Just selecting the DOM element using getElementById or querySelector will do the trick in regular JavaScript applications, however in ReactJS this is a bad practice, instead, you should rely on the React Refs to obtain the DOM node whenever you need it.

What are React Refs

Refs help you to get access directly to DOM nodes or React elements created in the render method. As we mentioned previously, with the React logic, props should be the only way that a parent element should interact with their children's components. However, in such situations where it's out of our responsibility, the implementation of the old React component or just because we are creating a component that uses a javascript library that manipulates the regular DOM, React offers us the way to get out of the React workflow with the Refs.

There's a recommendation though, and that is that you should avoid using refs for any new code that can be done declaratively e.g instead of creating methods like open() and close(), a prop named isOpen should be the best way to proceed.

How to use React Refs (React >= 16.3)

The way of using React Refs changed since React 16.3, which now needs to be declared using React.createRef():

import React, { Component } from 'react';

class MyComponent extends Component {
    constructor(props) {
        super(props);

        // 1. CreateRef in the constructor method
        this.myRefElement = React.createRef();
    }

    componentDidMount(){
        // 2. Obtain the DOM Node from the created ref and the current property (DOMNode contains a DOM element, namely the div)
        const DOMNode = this.myRefElement.current;
    }

    render() {
        return (
            <div ref={this.myRefElement}></div>
        );
    }
}

export default MyComponent;

For our example of the component that allows the user to preview a 360 degrees image, we will create the ref and use the DOM element to initialize the third party library that creates the viewer:

import React, { Component } from 'react';
import ThirdParty360ViewerLibrary from 'ThirdParty360ViewerLibrary';

class ThreeSixtyViewer extends Component {
    constructor(props) {
        super(props);

        this.state = {
            image: props.image
        };

        // 1. CreateRef in the constructor method
        this.panoramicContainer = React.createRef();
    }

    componentDidMount(){
        // 2. Obtain the DOM Node
        const DOMNode = this.panoramicContainer.current;
        // if you console.log DOMNode you should get the real domNode
        // <div></div>

        // In the example, we should replace the DOMNode of our library just like this
        // let options = {};
        // ThirdParty360ViewerLibrary.initialize(DOMNode, options);
    }

    render() {
        return (
            <div ref={this.panoramicContainer}></div>
        );
    }
}

export default ThreeSixtyViewer;

How to use React Refs (React <= 16.3)

The old way to create refs was to use the callback method, so instead of passing a string as ref, you pass a callback function. So when the render occurs, the ref will be passed as argument to the callback, updating its value and allowing you to access the DOM element:

import React, { Component } from 'react';

class MyComponent extends Component {
    constructor(props) {
        super(props);

        // 1. CreateRef in the constructor method
        this.handleRef = this.handleRef.bind(this);
    }

    myDomNode = null;

    // 2. Declare the handleRef method callback to obtain the DOMNode
    handleRef(ref) {
        this.myDomNode = ref;
    }

    componentDidMount(){
        // <div></div>
        console.log(this.myDomNode);
    }

    // 3. Assign ref callback
    render() {
        return (
            <div ref={this.handleRef}></div>
        );
    }
}

export default MyComponent;

And that's how easy it is to obtain access to a specific DOM element that you can use in your React Workflow. 

Happy coding ❤️!

References and external resources

This could interest you

Become a more social person