DEV Community

Cover image for Unlocking the Power of useRef: Besic to Advanced Examples for React Developers
Mahabubur Rahman
Mahabubur Rahman

Posted on

Unlocking the Power of useRef: Besic to Advanced Examples for React Developers

React, the popular JavaScript library for building user interfaces, offers a plethora of hooks to manage state, side effects, and more. Among these, useRef stands out as a versatile tool for accessing and managing references to DOM elements or other values across renders. In this article, we'll delve into how useRef works, its various use cases, and provide insightful examples to grasp its functionality from different perspectives.

Understanding useRef

useRef is a hook provided by React that returns a mutable ref object. This ref object persists across renders and allows us to keep values mutable without triggering re-renders. Unlike state variables, changes to refs do not cause component re-renders. This makes useRef perfect for storing mutable values or accessing DOM elements imperatively.

Basic Usage

Let's start with a basic example to illustrate the usage of useRef. Consider a scenario where you want to focus an input field when a component mounts. Here's how you can achieve it using useRef:

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

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

  useEffect(() => {
    inputRef.current.focus();
  }, []);

  return <input ref={inputRef} />;
}

Enter fullscreen mode Exit fullscreen mode

In this example, useRef is used to create a reference to the input element. We then use useEffect to focus the input element when the component mounts by accessing the current property of the inputRef.

Managing Previous Values

Another interesting use case of useRef is to maintain values across renders without triggering re-renders. This can be handy when you need to compare previous and current values within a component. Let's see how you can achieve this:

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

function MyComponent() {
  const prevValue = useRef('');

  useEffect(() => {
    // Compare prev and current values
    console.log('Previous value:', prevValue.current);
    prevValue.current = 'New Value';
    console.log('Current value:', prevValue.current);
  });

  return <div>Check the console for logs</div>;
}

Enter fullscreen mode Exit fullscreen mode

In this example, prevValue is a ref object initialized with an empty string. Inside the useEffect, we log the previous value, update it, and then log the current value. This allows us to maintain the previous value across renders without causing re-renders.

Imperative DOM Manipulation

useRef is not limited to just storing values; it's also useful for imperative DOM manipulation. Let's consider an example where we want to measure the height of an element dynamically:

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

function MyComponent() {
  const [height, setHeight] = useState(0);
  const elementRef = useRef(null);

  useEffect(() => {
    setHeight(elementRef.current.clientHeight);
  }, []);

  return (
    <div ref={elementRef}>
      <p>Height of this div is: {height}px</p>
    </div>
  );
}

Enter fullscreen mode Exit fullscreen mode

Here, elementRef is used to create a reference to the div element. Inside the useEffect, we measure the height of the element using clientHeight and update the state accordingly.

Managing Timer Intervals

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

function Timer() {
  const intervalRef = useRef(null);

  useEffect(() => {
    intervalRef.current = setInterval(() => {
      console.log('Tick...');
    }, 1000);

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

  return <div>Timer is running. Check the console for ticks.</div>;
}

Enter fullscreen mode Exit fullscreen mode

In this example, useRef is used to maintain a reference to the interval created by setInterval(). The interval is cleared when the component unmounts, preventing memory leaks.

Accessing Child Components

import React, { useRef } from 'react';
import ChildComponent from './ChildComponent';

function ParentComponent() {
  const childRef = useRef();

  const handleClick = () => {
    childRef.current.doSomething();
  };

  return (
    <div>
      <ChildComponent ref={childRef} />
      <button onClick={handleClick}>Invoke Child Method</button>
    </div>
  );
}

Enter fullscreen mode Exit fullscreen mode

Here, useRef is employed to access methods or properties of a child component imperatively. This can be useful for invoking child component functions from the parent.

Tracking Scroll Position

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

function ScrollTracker() {
  const [scrollPos, setScrollPos] = useState(0);
  const scrollRef = useRef();

  useEffect(() => {
    const handleScroll = () => {
      setScrollPos(scrollRef.current.scrollTop);
    };

    scrollRef.current.addEventListener('scroll', handleScroll);

    return () => {
      scrollRef.current.removeEventListener('scroll', handleScroll);
    };
  }, []);

  return (
    <div ref={scrollRef} style={{ height: '200px', overflow: 'auto' }}>
      <p>Scroll position: {scrollPos}px</p>
      {/* Scrollable content */}
    </div>
  );
}

Enter fullscreen mode Exit fullscreen mode

This example demonstrates how useRef can be used to track and update the scroll position of an element, such as a scrollable container.

Creating Mutable Variables

import React, { useRef } from 'react';

function MutableVariable() {
  const countRef = useRef(0);

  const handleClick = () => {
    countRef.current++;
    console.log('Count:', countRef.current);
  };

  return (
    <div>
      <p>Count: {countRef.current}</p>
      <button onClick={handleClick}>Increment Count</button>
    </div>
  );
}

Enter fullscreen mode Exit fullscreen mode

Here, useRef is employed to create a mutable variable (countRef) whose value persists across renders without triggering re-renders.

Handling Uncontrolled Components

import React, { useRef } from 'react';

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

  const handleClick = () => {
    alert(`Input value: ${inputRef.current.value}`);
  };

  return (
    <div>
      <input type="text" ref={inputRef} />
      <button onClick={handleClick}>Get Input Value</button>
    </div>
  );
}

Enter fullscreen mode Exit fullscreen mode

In this example, useRef is used to access the value of an input field without using controlled component techniques. This can be handy for managing form inputs in certain scenarios

Conclusion

useRef is a powerful hook in React that provides a way to work with mutable values and perform imperative actions on DOM elements. Its versatility makes it indispensable in various scenarios, ranging from managing focus, storing previous values, to imperative DOM manipulation. By mastering useRef, you unlock a plethora of possibilities to enhance the functionality and performance of your React applications.

Top comments (0)