How to access DOM Nodes using refs in React

In React, Ref is a way we can get hold of DOM nodes in JSX in the render method. Without this, we use the conventional document.getElementById.

In this shot, we will learn how to use refs to get access to DOM nodes and class instances in React.

Refs and elements

To refer to an element in the render method of our component, we create a ref using the React.createRef API and pass it as an attribute value to the ref attribute.

Code

class App extends React.Component {
    componentDidMount() {
        this.divRef = React.createRef()
    }
    render() {
        return (
            <div>
                <div id="divR" ref={this.divRef}>App, here</div>
            </div>
        )
    }
}

We used React.createRef to generate a unique id ref and pass it to divRef. We want to get the DOM node of the div#divR element, so we set the ref attribute and point the value to the divRef.

With this, the DOM node of div#divR will be contained in the current property of the divRef: this.divRef.current will return a DOM node of the div#divR element.

Code

class App extends React.Component {
    componentDidMount() {
        this.divRef = React.createRef()
        this.divRef.current // hold the DOM node `HTMLDivElement` of the div#divR
    }

    render() {
        return (
            <div>
                <div id="divR" ref={this.divRef}>App, here</div>
            </div>
        )
    }
}

With this.divRef.current, we can now use any DOM APIs like innerHTML, innerValue, etc.

Using ref like this is synonymous to using the document.getElementById(...).

Code

class App extends React.Component {
    componentDidMount() {
        this.divRef = document.getElementById("divR") // hold the DOM node `HTMLDivElement` of the div#divR
    }

    render() {
        return (
            <div>
                <div id="divR">App, here</div>
            </div>
        )
    }
}

Code

Let’s see another usage:

class App extends React.Component {
    constructor() {
        this.state = {
            data: null
        }
    }

    componentDidMount() {
        this.inputRef = React.createRef()
    }

    handleClick = () => {
        this.setState({ data: this.inputRef.current.target.value })
    }

    render() {
        return ( 
            <div> 
                {this.state.data } 
                <input ref={this.inputRef} /> 
                <button onClick={this.handleClick}> Click Me </button> 
            </div>
        )
    }
}

We have input and a button. We have state data that holds the value typed in the input box. We used ref to get the DOM node of the input element. With the DOM node, we get the value typed in when the button is clicked.

As this.inputRef.current holds the DOM node of the input textbox, we use the target.value API in HTMLInputElement to get the value typed in the input box.

Refs and React.Components

Refs can also be used to get an instance of React Components.

Code

class TextInput extends React.Component {
    constructor() {
        this.inputRef = React.createRef()
    }

    getInputValue() {
        return this.inputRef.current.target.value
    }

    render() {
        return (
            <>
                <input ref={this.inputRef} /> 
            </>
        )
    }
}

class App extends React.Component {
    constructor() {
        this.state = {
            data: null
        }
    }

    componentDidMount() {
        this.textInputRef = React.createRef()
    }

    handleClick = () => {
        this.setState({ data: this.textInputRef.current.getInputValue() })
    }

    render() {
        return ( 
            <div> 
                {this.state.data } 
                <TextInput ref={this.textInputRef} />
                <button onClick={this.handleClick}> Click Me </button> 
            </div>
        )
    }
}

Here, we are attaching ref to TextInput, which is a class Component. We will get the instance in this.textInputRef.current. Here, we can call any methods in the TextInput class.

Above, we used it to get the input value of the text box in the TextInput class. The getInputValue in the TextInput class returns the value of the input box element. So, in App we call the method in this.textInputRef.getInputValue().

Refs and functional components

Refs cannot work in functional components because they don’t have instances. Instead, the function components should be converted to class components.

Code

function TextInput() {
    this.inputRef = React.createRef()
    TextInput.getInputValue = function() {
        return this.inputRef.current.target.value
    }
    return (
        <>
            <input ref={this.inputRef} /> 
        </>
    )
}

class App extends React.Component {
    constructor() {
        this.state = {
            data: null
        }
    }

    componentDidMount() {
        this.textInputRef = React.createRef()
    }

    handleClick = () => {
        this.setState({ data: this.textInputRef.current.getInputValue() })
    }

    render() {
        return ( 
            <div> 
                {this.state.data } 
                <TextInput ref={this.textInputRef} />
                <button onClick={this.handleClick}> Click Me </button> 
            </div>
        )
    }
}

The above won’t work because TextInput is a functional component. Creating refs through React.createRef in function components would work.

So, we can create and attach refs in function components so far, as they are elements and class components.

Code

class TextInput extends Component {
        constructor() {
            this.inputRef = React.createRef()
        }
        
        getInputValue = function() {
            return this.inputRef.current.target.value
        }

        render() {
            return (
                <>
                    <input ref={this.inputRef} /> 
                </>
            )
        }
    }

    function App(){
        const [state, setState] =  useState({data: null})
        this.textInputRef = React.createRef()

        handleClick = () => {
            this.setState({ data: this.textInputRef.current.getInputValue() })
        }

        return ( 
            <div> 
                {this.state.data } 
                <TextInput ref={this.textInputRef} />
                <button onClick={this.handleClick}> Click Me </button> 
            </div>
        )
    }

Conclusion

We just learned in a simple and fast way what refs are and how to use them.

Ref : Reactjs Blog.