React Hook: useRef
Tags: react, javascript, beginners
Published: 2023-05-21 01:35:37

While working with React Hooks, I came across useRef and encountered some uncertainty. To address this, I decided to refresh my knowledge and learn more about it.

In this blog article, I will discuss two main concepts and their use cases by providing sample code. These examples are based on the React Documentation, serving as a foundation for illustrating the concepts. 
[React Documentation](https://react.dev/reference/react/useRef)

**Syntax**
import { useRef } from 'react';
const ref = useRef(_initialValue_);

- An initial value can be of any type.
- It returns an object with a single property: 
  { current: initialValue }.
- The ref.current property is mutable, but it's important not to write or read ref.current during rendering.


**1. Referencing a value with a ref**

When a variable or state changes in React, it triggers a re-render. However, there are situations where we want to retain the value of a variable without triggering re-renders. This is where `useRef` comes in handy as it allows us to store and access such values. Some people often refer to this capability as having a 'box' to store the value.

First, let's see how `useRef` works.

```
import React, { useRef } from "react";

export default function Counter() {
  let ref = useRef(0);

  const handleClick = () => {
    console.log("ref.current", ref.current);
    ref.current = ref.current + 1;
  };

  return (
    <>
      <button onClick={handleClick}>Click!</button>
      <h3>{ref.current}</h3>
    </>
  )
}
```


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7tlx0pmnn2az6vo435ti.png)


When clicking the button, nothing happens; the value of 0 remains unchanged. However, if you inspect the console, you will notice that the counter is incrementing. In contrast, if you had used `useState`, the value of 0 on the browser would change as you click.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/puivanhcqxmppehik7an.png)

**Use cases**:
When using `setInterval` or `setTimeout` we get a numerical ID (intervalID or timeoutID). We need to keep this ID when canceling the interval or timeout (`clearInterval` or `clearTimeout`). 
When refreshing the page, we get a new ID again.

_The code below is from the React Document._

```
import React, { useState, useRef } from "react"

export default function Stopwatch() {
  const [startTime, setStartTime] = useState(null)
  const [now, setNow] = useState(null)
  const intervalRef = useRef(null)

  function handleStart() {
    setStartTime(Date.now())
    setNow(Date.now())

    clearInterval(intervalRef.current)
    intervalRef.current = setInterval(() => {
      setNow(Date.now())
    }, 10)
  }

  function handleStop() {
    clearInterval(intervalRef.current)
    console.log("intervalRef clear", intervalRef.current)
  }

  let secondsPassed = 0
  if (startTime != null && now != null) {
    secondsPassed = (now - startTime) / 1000
  }

  return (
    <>
      <h1>Time passed: {secondsPassed.toFixed(3)}</h1>
      <button onClick={handleStart}>Start</button>
      <button onClick={handleStop}>Stop</button>
    </>
  )
}
```

**2. Manipulating the DOM with a ref**

Yes, DOM!

With the use of `useRef`, we can accomplish the same thing using `useRef` instead of `document.getElementById('myInput').focus()`.


```
const myRef = userRef(null);   // { current: null }
<input ref={myRef} />
```

What these two lines of code do is create a reference to the corresponding DOM node and store it in myRef.current. By doing so, you gain the ability to access this specific DOM node within your event handlers and utilize the browser APIs that are available on it.

Now, this makes sense to me.
`myRef.current.style.color = 'red';`

Some methods of ref.current
Component methods: play(), pause(), open(), close()
DOM element: focus(), blur(), scrollIntoView()
DOM element: contains()

The `contains()` method allows you to check whether a specific DOM element is a descendant of the element associated with the ref. This functionality can be particularly useful for implementing open/close modal behavior.

```
function myComponent(){
    const divRef = useRef(null);

    function handleClick(){
        if(divRef.current.contains(event.target)){
            console.log("Clicked inside the div element or inside the modal.");
        } else {
            console.log("Clicked outside the div element. You can implement the close-the-modal function here.");
        }
    };

    return (
        <div ref={divRef} onClick={handleClick}>
            Click inside or outside this dev element.
        </div>
    )
}
```

In summary, `useRef` offers the ability to store a value without triggering re-renders and facilitates the manipulation of DOM elements, enabling the creation of dynamic functionalities.