19 Feb 2024




Beginner

useRef hook in React provides a way to persist values across renders without causing re-renders when the value changes. It primarily serves two purposes: accessing and persisting references to DOM elements and storing mutable values that persist between renders without causing re-renders.

Explanation of the useRef hook:

Purpose:

  1. DOM references: useRef allows you to reference DOM elements directly within functional components without relying on document.getElementById or similar methods.
  2. Holding mutable values: useRef can hold values that persist between renders without causing the component to re-render when the value changes. This is useful for storing mutable values that do not need to trigger re-renders.

Syntax:

const myRef = useRef(initialValue);
  • myRef: The object returned by useRef holds a current property that can be used to access the current value of the reference.
  • initialValue: Optional. It initializes the current property of the reference. The value provided as initialValue is not used for re-renders.

When to Use:

  • Accessing DOM elements: When you need to access or manipulate a DOM element imperatively.
  • Holding mutable values: When you need to store values that persist between renders without causing re-renders.

Accessing DOM Elements:

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

function MyComponent() {
  const inputRef = useRef(null);

  useEffect(() => {
    // Focus the input element on mount
    inputRef.current.focus();
  }, []);

  return (
    <div>
      <input type="text" ref={inputRef} />
    </div>
  );
}

In this example, useRef is used to create a reference to the input element. This reference can be accessed using inputRef.current, allowing you to imperatively call methods like focus() on the input element.

Holding Mutable Values:

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

function MyComponent() {
  const counterRef = useRef(0);
  const [renderCount, setRenderCount] = useState(0);

  const incrementCounter = () => {
    counterRef.current++;
    setRenderCount(renderCount + 1); // Triggers re-render
  };

  return (
    <div>
      <p>Counter: {counterRef.current}</p>
      <p>Render Count: {renderCount}</p>
      <button onClick={incrementCounter}>Increment Counter</button>
    </div>
  );
}

In this example, useRef is used to hold a mutable value (counterRef.current). Whenever incrementCounter is called, the value of counterRef.current is incremented without triggering a re-render. Meanwhile, renderCount is stored in the component's state and does trigger a re-render when updated.

Common Patterns:

  • Accessing child components: useRef can be used to access methods or properties of child components.
  • Storing previous values: You can use useRef to store and access previous values of state or props to perform comparisons or calculations.
  • Caching values: useRef can be used to cache values computed during render to avoid recomputation on subsequent renders.

⚠️ Cautions:

  • Mutable values: Be cautious when using mutable values stored in useRef, especially if they are expected to cause side effects.
  • Synchronization: Changes to useRef values do not trigger re-renders. You need to manage updates to the component's state separately if you want to trigger re-renders based on changes to useRef values.

Key Points of useRef:

  1. Creating a Ref Object: When you call useRef, it returns a mutable ref object with a .current property initialized to the initialValue provided. This ref object persists for the entire lifecycle of the component.

  2. Mutable Ref Object: The .current property of the ref object is mutable, meaning you can change its value directly without causing a re-render of the component.

  3. Accessing DOM Nodes: One common use case for useRef is to access DOM nodes directly. You can attach the ref object to a JSX element using the ref attribute, and then access the DOM node using the .current property.

    import React, { useRef, useEffect } from 'react';
    
    function MyComponent() {
      const inputRef = useRef(null);
    
      useEffect(() => {
        inputRef.current.focus();
      }, []);
    
      return <input ref={inputRef} />;
    }
    
  4. Preserving Values Between Renders: Another use case for useRef is to preserve values between renders without causing re-renders. Since changing the .current property of the ref object doesn't trigger a re-render, you can use useRef to store values that you want to persist across renders without affecting the rendering of the component.

    import React, { useRef } from 'react';
    
    function MyComponent() {
      const renderCount = useRef(0);
    
      renderCount.current++;
    
      return <div>Render count: {renderCount.current}</div>;
    }
    
  5. Imperative DOM Manipulation: useRef is useful for imperative DOM manipulation or any situation where you need to store mutable state that doesn't trigger a re-render.

reactjs
useref