eMoosavi
Weekly frontend dev braindumps
Unraveling the Mysteries of React.useRef()
React Components

Unraveling the Mysteries of React.useRef()

Deep Dive into React's useRef Hook

Jul 09, 2024 - 12:263 min read

The useRef hook in React can be a bit of a mystery until you understand its full potential. Unlike other hooks such as useState and useEffect, useRef does not notify you when its content is changed. This makes it perfect for holding mutable values that don’t need to trigger a re-render when they're updated.

Why Use useRef?

useRef can be helpful in various scenarios, such as:

  • Storing DOM Elements: You can store a reference to a DOM element and perform DOM manipulations.
  • Keeping Mutable Values: For instance, storing interval IDs or timeout references without causing re-rendering.
  • Persisting Values Across Renders: Useful in scenarios where you need to hold values that persist across renders but don’t trigger a re-render when changed.
import React, { useRef, useEffect } from 'react';

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

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

    return (
        <div>
            <input ref={inputRef} type="text" placeholder="Focus me on mount!" />
        </div>
    );
}

User Interface Best Practices

One of the best practices when dealing with complex UI interactions in React is to minimize unnecessary re-renders. By leveraging useRef, we can further optimize our components for performance.

Example: Avoiding Unnecessary Re-Renders

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

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

    useEffect(() => {
        intervalRef.current = setInterval(() => {
            setSeconds(prevSeconds => prevSeconds + 1);
        }, 1000);

        return () => clearInterval(intervalRef.current);
    }, []);

    return (
        <div>
            <h1>{seconds}</h1>
            <button onClick={() => clearInterval(intervalRef.current)}>
              Stop Timer
            </button>
        </div>
    );
}

In this example, the timer continues to increment by holding the interval ID in a ref, thus avoiding unnecessary re-renders.

Common Pitfalls

Despite its prowess, useRef can sometimes be misused, leading to hard-to-debug issues and unexpected behaviors.

  1. Ref Initial Value: Be mindful of the initial value you set for your refs. Unlike state, updating a ref does not trigger a re-render.
  2. Avoiding Dependencies on Refs: Avoid writing re-render logic that depends on ref values as they don’t opt-in to React’s rendering cycle. Instead, incorporate the values in your state or effect dependencies where needed.

Comparing with useState

One common beginner's question is how useRef is different from useState. While both can hold values, useState will cause a re-render of the component when changed, but useRef will not.

Example: Comparing Differences

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

function CounterComparison() {
    const [count, setCount] = useState(0);
    const countRef = useRef(0);

    const increaseCountWithState = () => {
        setCount(count + 1);
    };

    const increaseCountWithRef = () => {
        countRef.current += 1;
        console.log(countRef.current);
    };

    return (
        <div>
            <div>
                <p>useState count: {count}</p>
                <button onClick={increaseCountWithState}>Increase State Count</button>
            </div>
            <div>
                <p>useRef count: {countRef.current}</p>
                <button onClick={increaseCountWithRef}>Increase Ref Count</button>
            </div>
        </div>
    );
}

In this demo, you'll see the use of useRef won't trigger a re-render when updated, whereas useState will. This illustrates the importance of choosing the right tool for the job.

Conclusion

useRef is a powerful and versatile hook that can handle scenarios where mutability is needed without causing re-renders. Understanding and using it correctly can significantly enhance the performance and readability of your React applications. Experiment and incorporate the useRef in practical ways to see how this hook can best suit your components' needs.

Article tags
reactreact-hooksuse-refweb-development
Previous article

Frontend Architecture

Advanced Optimizations with React Reconciliation

Next article

React Components

Deep Dive into Building Dynamic Data Tables with React and Ag-Grid