ReactJS - Refs and the DOM



React automatically emits the HTML elements as the state of the component changes. This greatly simplifies the UI development as it is enough to update the state of the component. But, traditionally, accessing the DOM element directly is the norms to update the UI of the component.

Sometimes we may need to fallback to accessing the DOM elements directly and update the UI in the react application as well. React ref lends help in this scenario. It provides direct access to DOM elements. Also, it make sure that the component work smoothly with react Virtual DOM and HTML DOM.

React provides a function, createRef to create ref in class based component. Let us learn how to use createRef in this chapter.

Signature of the createRef method

The purpose of the createRef is to return a mutable object, which will persist between rerenders. The signature of createRef is as follows −

<refObj> = React.createRef()

Here, refObj is the object returned by the hook

To automatically attach a DOM object to the refObj, it should be set in ref props of the element as shown below −

<input ref={refObj} />

To access the attached DOM element, use current property of the refObj as shown below −

const refElement = refObj.current

Applying ref

Let us learn how to apply createRef by creating a react application in this chapter.

First of all, create a new react application and start it using below command.

create-react-app myapp
cd myapp
npm start

Next, create a react component, SimpleRef under component folder (src/components/SimpleRef.js)

import React from "react";
class SimpleRef extends React.Component {
   render() {
      return (
         <div>Hello World</div>
      );
   }
}
export default SimpleRef;

Next, open App.css (src/App.css) and remove all the styles. Then, open App component (src/App.js) and update the content with our new SimpleRef component as shown below −

import './App.css'
import SimpleRef from './Components/SimpleRef'
function App() {
   return (
      <div className="container">
         <div style={{ padding: "10px" }}>
            <div>
               <SimpleRef />
            </div>
         </div>
      </div>
   );
}
export default App;

Next, add a counter functionality to SimpleRef component as shown below −

import React from "react";
class SimpleRef extends React.Component {
   
   constructor(props) {
      super(props)
      this.state = {
         count: 0
      }
      this.handleClick = this.handleClick.bind(this);
   }
   handleClick() {
      this.setState(
         prevState => ({
            count: prevState.count + 1
         })
      )
   }
   render() {
      return (
         <div>
            <div>Counter: {this.state.count} <button onClick={this.handleClick}>+</button></div>
         </div>
      )
   }
}
export default SimpleRef;

Here we have,

  • Used this.setState to handle counter state variable (count).

  • Rendered the counter state variable in the JSX

  • Added a button and attached a click handler event (this.handleClick), which will increment the counter using this.setState method

Next, add an input field and show a greeting message based on the value entered by user in the input field as shown below −

import React from "react";
import { createRef } from "react";
class SimpleRef extends React.Component {
   constructor(props) {
      super(props)
      this.state = {
         count: 0
      }
      this.handleClick = this.handleClick.bind(this);
      this.handleChange = this.handleChange.bind(this);
      this.inputRef = createRef()
      this.labelRef = createRef()
   }
   handleClick() {
      this.setState(prevState => ({
         count: prevState.count + 1
      }))
   }
   handleChange() {
      this.labelRef.current.innerText =
      this.inputRef.current.value == "" ? "World" : this.inputRef.current.value
   }
   render() {
      return (
         <div>
            <div>Counter: {this.state.count} <button onClick={this.handleClick}>+</button></div>
            <div style={{ paddingTop: "5px"}}>
               <label>Enter your name: </label><input type="text" name="username"
                  ref={this.inputRef} onChange={this.handleChange}/>
               <br />
               <div>Hello, <span ref={this.labelRef}></span></div>
            </div>
         </div>
      )
   }
}
export default SimpleRef;

Here we have,

  • Created a ref, this.inputRef to represent the input element and attached it to the relevant element through ref props

  • Created a ref, this.labelRef to represent the greeting message element and attached it to the relevant element through ref props

  • Attached an event handler, this.handleChange to the input element. The event handler uses this.inputRef ref to get the greeting message and uses this.labelRef ref to update the message

Next, open the application in the browser and enter your name. Application will update the greeting message as shown below.

Applying Ref

Check your console and you can notice that the component is not rerendered. Since react rerenders only on state changes and ref does not do any state changes, the component is not rerendered.

Next, click the + button. It will update the counter by rerendering the component as there is change in state (count). If you notice closely, you can find that the message remains same. The reason for this behavior is that the ref values are preserved between rendering by the react.

Use cases of createRef

Some of the use cases of createRef are as follows −

Accessing JavaScript DOM API − JavaScript DOM API provides rich set of feature to manipulate the UI of9 the application. When the application feature need access to JavaScript DOM API, createRef can be used to retrieve the raw DOM object. Once the raw DOM object is retrieved, the application can use the DOM API to access all the features. Some of the examples of DOM API are as follows −

  • Focusing an input element

  • Selecting text

  • play audio or video using media playback API

Imperative animation − Web Animation API provides a rich set of animation feature through imperative programming rather than declarative programming. To use Web animation API, we need access to the raw DOM.

Integration with third party library − Since third party library requires access to raw DOM to do its functionality, it is be mandatory to use createRef to get the DOM reference from react and provide it to third party library.

Summary

Even though react way of developing UI is simple and easy, developing UI based on DOM API has it own advantages in certain scenario. createRef hook fits perfectly in those scenario and provides simple and clean API to access the DOM element directly and subsequently its API.

Advertisements