Popular Searches
Popular Course Categories
Popular Courses

useRef Hook

useRef Hook

React Hooks Fundamentals

React useRef Hook – Complete Detailed Notes

The useRef Hook is a built-in React Hook that allows functional components to retain a mutable value between renders without triggering a re-render when that value changes. It is commonly used to access DOM elements, focus input fields, store timer IDs, track previous values, and interact with browser APIs.

React JS Training: JustAcademy React JS Training Course

Course Demo: Register for React JS Course Demo


1. What Is the useRef Hook?

The useRef Hook creates a reference object that contains a property called current. React retains the same ref object between renders of the same component instance. You can update its current property to store information without asking React to render the component again.

Syntax:

import { useRef } from 'react';
const myRef = useRef(initialValue);

Explanation:

  • useRef is the React Hook used to create a reference.
  • initialValue is the value assigned to current during initialization.
  • myRef is the reference object returned by React.
  • myRef.current is the property used to read or update the stored value.
  • Changing myRef.current does not trigger a component re-render.

2. Why Do We Need useRef?

Sometimes a React component needs to remember information that does not directly control what appears on the screen. In such situations, useRef can store that information without triggering unnecessary renders.

Common use cases:

  • Accessing HTML elements such as input fields, buttons, and video elements.
  • Automatically focusing an input field.
  • Scrolling an element into view.
  • Storing timer and interval IDs.
  • Remembering a previous value for comparison.
  • Keeping mutable information between renders.
  • Integrating with browser APIs or third-party libraries.
  • Controlling video playback or interacting with other DOM methods.

3. How Does useRef Work?

  1. The component calls useRef(initialValue).
  2. React returns a reference object containing the current property.
  3. The component can access the value through myRef.current.
  4. The value can be updated from an event handler or Effect.
  5. React retains the ref object between renders.
  6. Updating the ref does not itself trigger a re-render.

Basic flow:

Component renders
       ↓
useRef(initialValue)
       ↓
Ref object created or reused
       ↓
Access or update ref.current
       ↓
Value is retained between renders
       ↓
No re-render is triggered by the ref update

4. Basic Example of useRef

This example stores a number in a ref and increases it whenever a button is clicked.

import { useRef } from 'react';
function Counter() {
  const countRef = useRef(0);
  function increment() {
    countRef.current = countRef.current + 1;
    alert(`Current count: ${countRef.current}`);
  }
  return (
    <div>
      <h2>useRef Example</h2>
      <button onClick={increment}>Increment Ref</button>
    </div>
  );
}
export default Counter;

Explanation:

  • useRef(0) initializes the ref with the value zero.
  • countRef.current accesses the current stored value.
  • Each click increases the value by one.
  • The alert displays the updated value.
  • The component does not re-render merely because the ref changes.

Important: If you display {countRef.current} in JSX, the displayed number will not automatically update when the ref changes. Use useState when a value must update the visible UI.

5. Accessing DOM Elements with useRef

One of the most common uses of useRef is accessing a DOM element directly. When a ref is attached to an element using the JSX ref attribute, React assigns the corresponding DOM node to ref.current after the node is created.

Example: Access an input field

import { useRef } from 'react';
function InputExample() {
  const inputRef = useRef(null);
  function showInputValue() {
    alert(inputRef.current.value);
  }
  return (
    <div>
      <input ref={inputRef} type="text" placeholder="Enter your name" />
      <button onClick={showInputValue}>Show Value</button>
    </div>
  );
}
export default InputExample;

Explanation:

  • useRef(null) creates a ref initialized to null.
  • ref={inputRef} connects the ref to the input element.
  • After React mounts the input, inputRef.current refers to the DOM element.
  • inputRef.current.value reads the input's current text.
  • The button handler reads the value when the user clicks it.

6. Example: Automatically Focus an Input Field

The useRef Hook can focus an input programmatically when a user clicks a button.

import { useRef } from 'react';
function FocusInput() {
  const inputRef = useRef(null);
  function handleFocus() {
    inputRef.current?.focus();
  }
  return (
    <div>
      <h2>Focus Input Example</h2>
      <input ref={inputRef} type="text" placeholder="Enter your name" />
      <button onClick={handleFocus}>Focus Input</button>
    </div>
  );
}
export default FocusInput;

Explanation: When the user clicks the button, the handler calls the input element's focus() method. The optional chaining operator ?. prevents an error if the ref is currently null.

Practical applications: Login forms, search fields, registration forms, and search bars.

7. Example: Scrolling an Element into View

The useRef Hook can access an element so that browser methods such as scrollIntoView() can be used.

import { useRef } from 'react';
function ScrollExample() {
  const sectionRef = useRef(null);
  function scrollToSection() {
    sectionRef.current?.scrollIntoView({
      behavior: 'smooth',
      block: 'start'
    });
  }
  return (
    <div>
      <button onClick={scrollToSection}>Go to Section</button>
      <div style={{ height: '500px' }}>Scroll down to find the section.</div>
      <section ref={sectionRef}>
        <h2>Target Section</h2>
        <p>You have reached the target section.</p>
      </section>
    </div>
  );
}
export default ScrollExample;

Explanation: Clicking the button calls scrollIntoView() on the referenced section. The browser smoothly scrolls to that element.

8. useRef vs. useState

Both useRef and useState can retain information between renders, but they serve different purposes.

Feature useRef useState
Purpose Stores values not directly used to render the UI Stores values that affect the UI
Returns An object with a current property An array containing the current value and setter function
Updating the value Assign a new value to ref.current Call the setter function
Triggers re-render No, not by itself Requests a re-render when the state changes
Mutability The current property is mutable State should be treated as immutable
Typical use DOM references and timer IDs Input values, counters, and visible UI state

Example: Use useState for a counter number that must update on the screen. Use useRef for a timer ID that needs to be stored so it can later be cleared.

9. Storing Timer IDs with useRef

A timer ID can be stored in a ref so that it remains available between renders. This is useful when a component needs Start and Stop buttons.

import { useRef, useState } from 'react';
function TimerControl() {
  const timerRef = useRef(null);
  const [seconds, setSeconds] = useState(0);
  function startTimer() {
    if (timerRef.current !== null) return;
    timerRef.current = setInterval(() => {
      setSeconds(previousSeconds => previousSeconds + 1);
    }, 1000);
  }
  function stopTimer() {
    if (timerRef.current !== null) {
      clearInterval(timerRef.current);
      timerRef.current = null;
    }
  }
  return (
    <div>
      <h2>Seconds: {seconds}</h2>
      <button onClick={startTimer}>Start</button>
      <button onClick={stopTimer}>Stop</button>
    </div>
  );
}
export default TimerControl;

Explanation:

  • timerRef stores the interval ID.
  • startTimer() starts the interval only if one is not already running.
  • stopTimer() clears the interval and resets the ref to null.
  • seconds is state because its value must update the displayed UI.

Important: In a complete application, also clear the interval when the component unmounts. You can do this with an appropriate cleanup function in useEffect.

10. Example: Remembering a Previous Value

A ref can store a value from an earlier render. This pattern is useful when you need to compare a previous value with the current one.

import { useEffect, useRef, useState } from 'react';
function PreviousValue() {
  const [count, setCount] = useState(0);
  const previousCountRef = useRef();
  useEffect(() => {
    previousCountRef.current = count;
  }, [count]);
  return (
    <div>
      <p>Current Count: {count}</p>
      <p>Previous Count: {previousCountRef.current ?? 'Not available'}</p>
      <button onClick={() => setCount(previous => previous + 1)}>Increment</button>
    </div>
  );
}
export default PreviousValue;

Explanation: The Effect saves the committed count value in the ref. On a subsequent render, the ref can hold the count from the previous committed render. This simple example may show an initial placeholder before the Effect runs; the ref update itself does not trigger a render.

11. useRef with Controlled Input Fields

A controlled input normally uses useState to store its value. A ref can still be used to focus the input or access its DOM methods.

import { useRef, useState } from 'react';
function ControlledInput() {
  const [name, setName] = useState('');
  const inputRef = useRef(null);
  function clearInput() {
    setName('');
    inputRef.current?.focus();
  }
  return (
    <div>
      <input
        ref={inputRef}
        value={name}
        onChange={event => setName(event.target.value)}
        placeholder="Enter your name"
      />
      <button onClick={clearInput}>Clear and Focus</button>
      <p>Name: {name}</p>
    </div>
  );
}
export default ControlledInput;

Explanation: useState controls the input value and keeps the displayed text synchronized with React. useRef accesses the DOM node to focus it. This demonstrates how the two Hooks can work together.

12. useRef and the Component Lifecycle

A ref object is retained between renders of the same mounted component instance. Its current property may hold different values over time.

  • Initial render: A ref is created with the supplied initial value.
  • After a DOM node mounts: If the ref is attached to that node, React assigns the DOM node to current.
  • During later renders: React returns the same ref object.
  • When the referenced DOM node is removed: React resets that DOM ref's current property to null.
  • When the component unmounts: The ref is no longer retained as part of that component instance.

13. Rules and Best Practices for useRef

  • Call useRef only at the top level of a function component or custom Hook.
  • Do not call useRef inside loops, conditions, or nested functions.
  • Use ref.current to read or update the stored value in event handlers and Effects.
  • Do not read or write ref.current during rendering, except for predictable initialization logic.
  • Use useState instead when a value must cause the UI to update.
  • Use refs as an escape hatch for DOM interaction and mutable values that do not drive rendering.
  • Clean up timers, subscriptions, and other resources when necessary.
  • Use meaningful names such as inputRef, timerRef, and videoRef.

14. Common Mistakes When Using useRef

Mistake Why It Is a Problem Correct Approach
Expecting a re-render Updating ref.current does not trigger a re-render Use useState for visible UI changes
Accessing a DOM ref too early The element may not have mounted yet Access the DOM ref in an event handler or Effect after mounting
Forgetting to clear a timer The interval may continue running unnecessarily Clear the timer when it is no longer needed
Reading a ref during rendering May lead to unpredictable rendering behavior Read it in handlers or Effects instead
Using useRef for visible data Changes will not automatically update the screen Use state for values that affect rendered output
Calling useRef conditionally Breaks the Rules of Hooks Call it at the top level of the component

15. useRef vs. createRef

React provides both useRef and createRef, but they are commonly used in different situations.

Feature useRef createRef
Typical usage Function components Class components and other explicit ref creation scenarios
Object identity Returns the same ref object across renders of the same component instance Creates a new ref object each time it is called
Common purpose Retaining a value or DOM reference between renders Creating a ref object, often as a class field

16. Practical Project: Focus Input Application

Project objective: Create a simple application that lets users focus an input field and clear its content.

Features:

  • Enter text in an input field.
  • Click a button to focus the input.
  • Click another button to clear the input.
  • Use useRef for DOM access.
  • Use useState to control the input value.

Code:

import { useRef, useState } from 'react';
function FocusInputApp() {
  const [text, setText] = useState('');
  const inputRef = useRef(null);
  function focusInput() {
    inputRef.current?.focus();
  }
  function clearInput() {
    setText('');
    inputRef.current?.focus();
  }
  return (
    <div>
      <h1>Focus Input Application</h1>
      <input
        ref={inputRef}
        value={text}
        onChange={event => setText(event.target.value)}
        placeholder="Type something"
      />
      <button onClick={focusInput}>Focus Input</button>
      <button onClick={clearInput}>Clear Input</button>
      <p>Entered Text: {text}</p>
    </div>
  );
}
export default FocusInputApp;

Learning outcomes:

  • Understand how to create and use a ref.
  • Access DOM elements through the ref attribute.
  • Call browser DOM methods from event handlers.
  • Combine useRef and useState in a practical React component.

17. Practice Exercises

  1. Create a button that focuses an input field using useRef.
  2. Create a page that scrolls to a selected section.
  3. Store a timer ID in a ref and implement Start and Stop buttons.
  4. Build a controlled input with Clear and Focus buttons.
  5. Use a ref to access a video element and play or pause it.
  6. Store a previous value in a ref and compare it with the current state.
  7. Create a counter using useRef and observe why the displayed value does not update automatically.
  8. Combine useState, useRef, and useEffect to create a stopwatch with Start, Stop, and Reset controls.

18. Interview Questions and Answers

Q1. What is the useRef Hook?

Answer: useRef is a React Hook that stores a mutable value between renders without triggering a re-render when its current value changes.

Q2. What does useRef return?

Answer: It returns an object with a current property.

Q3. Does changing ref.current cause a re-render?

Answer: No. Updating the current property does not automatically trigger a re-render.

Q4. What is the most common use of useRef?

Answer: Accessing DOM elements to perform actions such as focusing an input, scrolling to an element, or interacting with a video.

Q5. What is the difference between useRef and useState?

Answer: useRef stores mutable information without triggering a re-render. useState stores state that can trigger a re-render when updated.

Q6. Why is null commonly passed to useRef?

Answer: A DOM element may not exist during the initial render. Initializing its ref with null represents the absence of the element until React attaches it.

Q7. Can useRef store values other than DOM elements?

Answer: Yes. It can store timer IDs, numbers, strings, objects, and other values that do not directly drive rendering.

Q8. Can useRef replace useState?

Answer: Not in every situation. If a value must update the visible UI, useState is generally appropriate. useRef is better for mutable values that do not need to trigger rendering.

Q9. What happens to a DOM ref when its element is removed?

Answer: React resets the DOM ref's current property to null when the referenced element is removed.

Q10. Can useRef be called inside an if statement?

Answer: No. Like other ordinary Hooks, useRef must be called at the top level of a function component or custom Hook.

19. Quick Revision Checklist

  • Understand the purpose and syntax of useRef.
  • Know how to read and update ref.current.
  • Understand why changing a ref does not trigger a re-render.
  • Practice focusing inputs and accessing DOM elements.
  • Know how to store timer IDs in refs.
  • Understand the difference between useRef and useState.
  • Practice combining useRef with useEffect.
  • Follow the Rules of Hooks.
  • Avoid reading or writing refs during rendering, except for predictable initialization.
  • Build practical projects using DOM references.

20. Conclusion

The useRef Hook is an important React feature for retaining mutable information and interacting with DOM elements without triggering unnecessary re-renders. By learning DOM references, input focusing, timer management, previous-value tracking, and the difference between useRef and useState, developers can build more effective React applications.

Continue learning with the JustAcademy React JS Training Course or register for a React JS course demo.

whatsapp