useRef Hook

Loading

The useRef hook is a versatile hook in React that allows you to persist values across renders without triggering re-renders. It is commonly used for accessing DOM elements directly or storing mutable values that do not require re-rendering when updated.

1. What is the useRef Hook?

The useRef hook returns a mutable object with a .current property. This object persists across renders, and it doesn’t cause a re-render when its value changes. It’s mainly used for:

  • Accessing DOM elements: Directly referencing DOM nodes without using document.querySelector or getElementById.
  • Storing mutable values: Keeping track of values (like previous state, timers, or counters) that don’t trigger a re-render when updated.

2. Basic Syntax of useRef

const myRef = useRef(initialValue);
  • initialValue: The value that you want the ref to be initialized with (optional). If not provided, it defaults to null.

The myRef object returned by useRef contains a single property .current, which can hold any value you want.

3. Accessing DOM Elements

One of the most common uses of useRef is to reference DOM elements directly without causing re-renders. This can be useful when you need to focus an input field, measure its size, or perform other DOM manipulations.

Example: Accessing DOM Elements

import React, { useRef } from 'react';

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

  const focusInput = () => {
    inputRef.current.focus();  // Focuses the input element directly
  };

  return (
    <div>
      <input ref={inputRef} type="text" />
      <button onClick={focusInput}>Focus the input</button>
    </div>
  );
}

export default FocusInput;

In this example:

  • inputRef is a reference to the input element.
  • When the button is clicked, the focusInput function calls inputRef.current.focus(), focusing the input field without triggering a re-render.

4. Storing Mutable Values

You can also use useRef to store mutable values that don’t require re-renders. This is useful for keeping track of previous state, interval IDs, or any other value that should persist across renders but not trigger a re-render.

Example: Storing Mutable Values

import React, { useState, useEffect, useRef } from 'react';

function Timer() {
  const [seconds, setSeconds] = useState(0);
  const prevSecondsRef = useRef();

  useEffect(() => {
    prevSecondsRef.current = seconds;
  }, [seconds]);

  return (
    <div>
      <p>Current Seconds: {seconds}</p>
      <p>Previous Seconds: {prevSecondsRef.current}</p>
      <button onClick={() => setSeconds(seconds + 1)}>Increment</button>
    </div>
  );
}

export default Timer;

In this example:

  • prevSecondsRef stores the previous value of seconds.
  • The useEffect hook updates the prevSecondsRef.current value whenever seconds changes, allowing you to track the previous value without causing a re-render.

5. useRef vs. useState

While both useRef and useState can hold data, they behave differently:

  • useState: Triggers a re-render when the value changes.
  • useRef: Does not trigger a re-render when the value changes.

Use useRef when you want to keep track of values across renders, but you don’t need React to re-render the component when the value changes. Use useState when the state change should trigger a re-render of the component.

6. useRef for Timer or Interval IDs

When you need to store references to timers or intervals, useRef is perfect because it allows you to access and clear timers or intervals without causing re-renders.

Example: Storing Interval ID

import React, { useEffect, useRef } from 'react';

function Stopwatch() {
  const intervalRef = useRef(null);
  const [seconds, setSeconds] = useState(0);

  useEffect(() => {
    if (intervalRef.current) {
      clearInterval(intervalRef.current);
    }
  }, []);

  const startTimer = () => {
    intervalRef.current = setInterval(() => {
      setSeconds(prev => prev + 1);
    }, 1000);
  };

  const stopTimer = () => {
    clearInterval(intervalRef.current);
  };

  return (
    <div>
      <p>Time: {seconds}s</p>
      <button onClick={startTimer}>Start</button>
      <button onClick={stopTimer}>Stop</button>
    </div>
  );
}

export default Stopwatch;

In this example:

  • intervalRef.current stores the ID of the interval, which allows you to clear it when needed, preventing memory leaks.

7. When to Use useRef

  • Accessing DOM Elements: When you need to directly manipulate or access a DOM element (e.g., focusing an input, scrolling, measuring the size).
  • Storing Mutable Values: When you want to keep track of values that don’t need to trigger re-renders (e.g., previous state, timers, interval IDs).
  • Performance Optimization: useRef can help avoid unnecessary re-renders that might be triggered by using useState when the state doesn’t actually need to affect the UI.

Leave a Reply

Your email address will not be published. Required fields are marked *