Understanding the basics of React Refs
Tags: webdev, react, javascript, learning
Published: 2024-01-05 17:26:39

# What are Refs

In the simplest way possible, React refs (which is short for references) are functions that React provides you to reference and interact with DOM nodes and React components directly.[[1](https://www.geeksforgeeks.org/reactjs-refs/)][[2](https://blog.logrocket.com/complete-guide-react-refs/)]

# Creating Refs

There are two ways to create refs, either use the `createRef` method or the `useRef` hook.[[2](https://blog.logrocket.com/complete-guide-react-refs/)]

## What’s the difference?

The `createRef` method is meant to be used with class components where whereas the `useRef` hook is meant to be used with function components.[[2](https://blog.logrocket.com/complete-guide-react-refs/)]

I don’t use class components so from this point onwards I am going to pretend like the `createRef` method does not exist.

## Creating Refs Using the `useRefs` Hook

As mentioned earlier, you can add refs to your component using the `useRef` hook.

```tsx
// source: https://react.dev/learn/referencing-values-with-refs
import { useRef } from 'react'

// Here a button will increment ref.current on every click
const Counter = () => {
	const ref = useRef(0)
	const handleClick = () => {
		ref.current = ref.current + 1
		alert(`You have clicked the button ${ref.current} times.`)
	}
	return (
		<button onClick={handleClick} >
			Click Me
		</button>
	)
}
```
> Note: The `useRef` hook allows you to set an initial value of any type, but this value is ignored after the initial render.[[3](https://blog.logrocket.com/complete-guide-react-refs/)]

`useRef` returns an object with a single property, `current`. If you pass an initial value into `useRef`, `current` will be set to that value, but once the ref object is passed into the ref attribute of a JSX node, whatever initial value set will be overridden by a value set by React. [[3](https://react.dev/reference/react/useRef)]

# When to use Refs

Typically, you will use a ref when you need your component to communicate with some external from React, often a browser API that won’t impact the component's appearance. Other possible reasons to use refs are to:

- Store timeout IDs
- Store and manipulate DOM elements
- Store other elements that aren’t necessary to calculate the JSX

If your component needs to store some value, but it does not impact the rendering logic, choose refs.[[4](https://react.dev/learn/referencing-values-with-refs)]

# Best practices for refs

Following these principles will make your components more predictable:

- **Treat refs as an escape hatch**: In other words, consider refs as a way to access and modify the lower-level behaviour of DOM nodes that React normally abstracts away.[[4](https://react.dev/learn/referencing-values-with-refs)]
- **Don’t read or write `ref.current` during rendering**: If some information is needed during rendering, use state instead because React doesn’t keep track of when `ref.current` changes. The only exception to this is code like `if (!ref.current) ref.current = new Thing()` which only sets the ref once during the first render.[[4](https://react.dev/learn/referencing-values-with-refs)]

# Common Use Cases

The following is a list of some of the ways you might use refs in your components.

## Focus Control

Programmatically focusing on an input element can be an easy way to improve user experience, cutting out the need for the user to manually drag their cursor over to the input field.

```tsx
import { useRef, useState, useEffect } from 'react'

const LoginForm = () => {
	const ref = useRef(null)
	const [email, updateEmail] = useState()
	const [password, updatePassword] = useState()
	const handleClick = (e, updateValue) => {
	...
	}

	useEffect(() => {
	if(ref.current){
		ref.current.focus()
	}
}, [])
	
	return (
		<div>
				<h1>Insert a new value</h1>
				<form>
					<input 
						placeholder="Email" 
						ref={ref} 
						type="text" 
						onChange={(e) => handleChange(e, updateEmail)} 
						value={email} />
					<input 
						placeholder="Password" 
						type="password" 
						value={password} 
						onChange={(e) => handleChange(e, updatePassword)} />
					<button>Save</button>
				</form>
		</div>
	)
}
```

The code above works by passing the ref to the email input field. React assigns the input node to `ref.current`, which gives lower-level access to the node, which means we can call the focus method on the initial page load to automatically have the email input field focused and ready to receive input. 

> Link to the sandbox: https://codesandbox.io/p/sandbox/focus-on-render-9l7st4
> 

## Triggering Animations

Another common use case for refs is to use them as part of a trigger for some animation on an element. The code example below triggers a slide-in animation on some text when the element enters the viewport.

```tsx
import React, { useEffect, useRef, useState } from "react";

const App = () => {
  const elementRef = useRef<HTMLDivElement | null>(null);

  useEffect(() => {
    const node = elementRef.current;
    const observer = new IntersectionObserver((entries) => {
      entries.forEach((entry) => {
        if (entry.isIntersecting) {
          entry.target.classList.add(
						"animate-in", 
						"slide-in-from-bottom", 
						"opacity-100"
					);
          entry.target.classList.remove("opacity-0");
        } 
      });
    });

    if (node) {
      observer.observe(node);
    }

    return () => {
      if (node) {
        observer.unobserve(node);
      }
    };
  }, []);

  return (
    <>
      <div className="h-screen grid place-items-center">
        <p className="text-7xl">What it do!</p>
      </div>
      <div id="animation-section" className="h-screen grid place-items-center">
        <p
          className="text-7xl slide-in-from-bottom duration-300 delay-100 transition opacity-0"
          ref={elementRef}
        >
          This should slide in from the bottom.
        </p>
      </div>
    </>
  );
};

export default App;
```

Sources:

1. [https://www.geeksforgeeks.org/reactjs-refs](https://www.geeksforgeeks.org/reactjs-refs/)
2. https://blog.logrocket.com/complete-guide-react-refs/
3. https://react.dev/reference/react/useRef
4. https://react.dev/learn/referencing-values-with-refs