DEV Community

Mihir Chhatre
Mihir Chhatre

Posted on • Updated on

React useRef() 🪝

useRef() is similar to useSate() as it allows us to persist(remain unchanged) values between renders but unlike useState(), the Ref hook does not cause a re-render when the mutable value is changed.

useRef() returns a mutable object whose current property is set with an initial value that is passed as an argument to the Ref function.

const refObject = useRef(initial_value);

In the above example, refObject is the returned object. This object has a current property that can be used to obtain the value of the referenced object at any time.

There are two primary uses of useRef() -

  1. To create persisted mutable variables(these are called refs or references).
  2. To access DOM elements(or React elements).

Let's dive into these.

1. useRef() to create persisted mutable variables

Trying to count the number of times a component re-renders using useState will lead to an infinite loop as useState itself causes a re-render. This is demonstrated in the example below.

import React,{useState, useEffect} from 'react'

function App() {

  const [text, setText] = useState('')
  const [count, setCount] = useState(0)

  useEffect(() => {
    setCount(prevStateCount => prevStateCount + 1)
  })

  return (
    <div>
      <input value={text} onChange={e=>setText(e.target.value)} />
      <div>Type some text in the box</div>
      <div>Component rendered {count} times</div>
    </div>
  )
}

export default App

Enter fullscreen mode Exit fullscreen mode

During initial component render, the 'count' is incremented which causes the component to re-render, and hence the count increments again leading to re-rendering the component. Essentially this is an infinite loop of incrementing 'count' and component re-rendering.

Refs to the rescue 🛟...
Refs can be used to solve the infinite loop issue that arises due to re-rendering when using the state hook.

import React,{useState, useEffect, useRef} from 'react'

function App() {

  const [text, setText] = useState('')
  const count = useRef(1)

  useEffect(() => {
    count.current = count.current + 1
  })

  return (
    <div>
      <input value={text} onChange={e=>setText(e.target.value)} />
      <div>Type some text in the box</div>
      <div>Component rendered {count.current} times</div>
    </div>
  )
}

export default App

Enter fullscreen mode Exit fullscreen mode

useRef() replaces useState() and count is an object with a current property. The current property persists as it is updated between different renders.

We can observe from the image below, each time a character is entered in the input field, the count increments. Since 'apple' is entered, the count is incremented 6 times (1 on initial render + increment by 1 for each character). Irrespective of the number of times the count changes, our component is not re-rendered since it is decoupled from our component render cycle.

Image showing a string apple entered into the input field, resulting in the count variable incrementing to 6

2. Accessing DOM elements

A more common use for Refs is when we need to reference HTML elements.

Every HTML element has a ref attribute. We can add the ref attribute to the element to access the element directly in the DOM.

Let's understand this use case with an example. Consider the code for a scenario where we want to focus on an input when a button is clicked.

import React,{useRef} from 'react'

function App() {

  const inputRef = useRef()

  const focus = () => {
    inputRef.current.focus()
  }
  return (
    <div>
      <input ref={inputRef} />
      <button onClick={focus}>Click to focus</button>
    </div>
  )
}

export default App
Enter fullscreen mode Exit fullscreen mode

Each time 'inputRef' is rendered on the screen, the 'inputRef' variable is set to the input element. Therefore, in the focus function, we are accessing 'inputRef' variable's current property(this corresponds to input element) and then focussing on it.

From the screenshot attached below, we can observe how clicking on the button focuses on the input.

Image shows the input field is focused

Another hack with useRef() 💡 -->
Imagine updating the state with every character when dealing with forms. This could be slightly excessive. Using Refs, we can set up a connection between the HTML element that is rendered eventually and other JavaScript code.


👏 Congratulations & great going 👏. You have now covered three React hooks. This would be a good point to re-collect your understanding of these hooks.

If you feel confident 😎, dive straight into Part 4 where I cover useReducer().

Oldest comments (0)