React useRef() 🪝
Tags: webdev, javascript, react, tutorial
Published: 2023-01-28 20:24:31

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.
<br>

### 1. <u>useRef() to create persisted mutable variables</u>

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.

```javascript
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

```
<br>

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.
<br>

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.

```javascript
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

```
<br>

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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/5502r2jjq4n2759va3rc.png)
<br>

### 2. <u>Accessing DOM elements</u>

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. 

```javascript
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
```

<br>

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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/np6jfmsl3tdid6m3jm3f.png)
<br>

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().