DEV Community

Joseph
Joseph

Posted on

Understanding the basics of React Refs

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][2]

Creating Refs

There are two ways to create refs, either use the createRef method or the useRef hook.[2]

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]

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.

// 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>
    )
}
Enter fullscreen mode Exit fullscreen mode

Note: The useRef hook allows you to set an initial value of any type, but this value is ignored after the initial render.[3]

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]

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]

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

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.

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>
    )
}
Enter fullscreen mode Exit fullscreen mode

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.

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;
Enter fullscreen mode Exit fullscreen mode

Sources:

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

Top comments (0)