React useRef Hook

The useRef Hook in React allows you to maintain values across renders without causing a re-render when the value changes.

It can be used to store a mutable value and directly access DOM elements.




Avoiding Re-renders

Using the useState Hook to count application renders can lead to an infinite loop as useState causes a re-render. Instead, the useRef Hook can be used to avoid this.

Example

Using useRef to track application renders:

import { useState, useEffect, useRef } from "react";
import ReactDOM from "react-dom/client";

function Application() {
  const [text, setText] = useState("");
  const renderCount = useRef(0);

  useEffect(() => {
    renderCount.current += 1;
  });

  return (
    <>
      <input
        type="text"
        value={text}
        onChange={(e) => setText(e.target.value)}
      />
      <h1>Render Count: {renderCount.current}</h1>
    </>
  );
}

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<Application />);

The useRef Hook returns an object called current. When initializing useRef, you set the initial value: useRef(0). It’s similar to: const renderCount = { current: 0 }. Access the count via renderCount.current.

Try running this code and typing in the input field to see the application render count increase.




Accessing DOM Elements

React typically handles all DOM manipulation. However, useRef can be used in specific cases without causing issues.

Add a ref attribute to an element to access it directly in the DOM.

Example

Using useRef to focus an input:

import { useRef } from "react";
import ReactDOM from "react-dom/client";

function Application() {
  const inputRef = useRef();

  const focusInputField = () => {
    inputRef.current.focus();
  };

  return (
    <>
      <input type="text" ref={inputRef} />
      <button onClick={focusInputField}>Focus Input</button>
    </>
  );
}

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<Application />);




Tracking State Changes

The useRef Hook can also keep track of previous state values since it persists values between renders.

Example

Using useRef to track previous state values:

import { useState, useEffect, useRef } from "react";
import ReactDOM from "react-dom/client";

function Application() {
  const [text, setText] = useState("");
  const previousText = useRef("");

  useEffect(() => {
    previousText.current = text;
  }, [text]);

  return (
    <>
      <input
        type="text"
        value={text}
        onChange={(e) => setText(e.target.value)}
      />
      <h2>Current Value: {text}</h2>
      <h2>Previous Value: {previousText.current}</h2>
    </>
  );
}

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<Application />);
Scroll to Top