ReactJS - useRef



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. Traditionally, it is normal to access the DOM element directly to update the UI of the component.

Sometimes we may need to fallback to accessing the DOM elements directly and update the UI of the component. 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. The counterpart of createRef in function component is useRef hook. Let us learn how to use useRef in this chapter.

Signature of the useRef hook

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

<refObj> = useRef(<val>)

Here,

  • val is the initial value to be set for the returned mutable object, refObj.

  • 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 hook

Let us learn how to apply useRef 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, RefInput under component folder (src/components/RefInput.js)

function RefInput() {
   return <div>Hello World</div>
}
export default RefInput

Next, update the root component (App.js) to use our new component.

import RefInput from "./components/RefInput";
function App() {
   return (
      <div style={{ padding: "5px"}}>
         <RefInput />
      </div>
   );
}
export default App;

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

import {useState} from 'react'
function RefInput() {
   const [count, setCount] = useState(0)
   const handleClick = () => setCount(count + 1)
   return (
      <div>
         <div>Counter: {count} <button onClick={handleClick}>+</button></div>
      </div>
   )
}
export default RefInput

Here we have,

  • Used useState hook to handle counter state variable (count).

  • Rendered the counter state variable in the JSX.

  • Added a button and attached a click handler event (handleClick), which will increment the counter using setCount 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 {useState, useRef} from 'react'
function RefInput() {
   const [count, setCount] = useState(0)
   const inputRef = useRef(null)
   const labelRef = useRef(null)
   console.log("RefInput is (re)rendered")
   const handleClick = () => setCount(count + 1)
   const handleChange = () => labelRef.current.innerText = inputRef.current.
   value == "" ? "World" : inputRef.current.value
   return (
      <div>
         <div>Counter: {count} <button onClick={handleClick}>+</button></div>
            <div style={{ paddingTop: "5px"}}>
               <label>Enter your name: </label><input type="text" name="username"
                  ref={inputRef} onChange={handleChange}/>
               <br />
            <div>Hello, <span ref={labelRef}></span></div>
         </div>
      </div>
   )
}
export default RefInput

Here we have −

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

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

  • Attached an event handler, handleChange to the input element. The event handler uses inputRef ref to get the greeting message and uses 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 Hook

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 useRef

Some of the use cases of useRef are as follows −

Accessing JavaScript DOM API − JavaScript DOM API provides rich set of feature to manipulate the UI of the application. When the application feature need access to JavaScript DOM API, useRef 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 useRef 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. useRef hook fits perfectly in those scenario and provides simple and clean API to access the DOM element directly and subsequently its API.

Advertisements