DEV Community

Tano Paul
Tano Paul

Posted on

useState vs useRef Hooks

React is a powerful tool that allows developers to create powerful websites and apps by combining the programming language of JavaScript with the power of HTML through the use of a syntax extension called JSX (JavaScript XML). In React, one of the more powerful tools is referred to as a "hook", which is a special function that allows you to "hook" onto or use special React features within functional components.

One of the most used hooks is the useState hook that allows you to store and manipulate data in your React program. Its use is essential if one is to build a website that a user is able to interact with. Something crucial to understand, which isn't necessarily a bad thing, is that useState causes re-renders every time the state is updated. In most cases, this is exactly what you want. However, there may be some cases that a developer doesn't want to re-render the component when updating a variable. This is where useRef comes in.

Getting Started with useRef

Like any other hook, the first thing you do is import it at the top of your component in order to declare it.

import { useRef } from 'react';
Enter fullscreen mode Exit fullscreen mode

When initializing useRef, the hook is called differently in both appearance and functionality than useState, which is stored as an array with a variable and setter function. With useRef, it's stored as an object thats key is always "current". You can then place a reference property on a JSX element to "refer" to that element.

const inputRef = useRef(any value);
console.log(inputRef)
// logged on console:   {current: input}
return (
    <div>
      <input ref={inputRef} />
      <button onClick={handleClick}>
        Focus the input
      </button>
    </div>
)
Enter fullscreen mode Exit fullscreen mode

Best Use Cases

Most of the time when working in React you'll want to use the useState hook rather than useRef, but there are some cases where useRef will come in handy.

Say you wanted to scroll an image into view. If a programmer used useState to accomplish this, after clicking a button to focus on another picture, useState will re-render the page to land on the desired image. With useRef, you can reference the element that does not need to re-render in order to reach the desired effect.

const listRef = useRef(null);

  function scrollToIndex(index) {
    const listNode = listRef.current;

    const imgNode = listNode.querySelectorAll('li > img')[index];
    imgNode.scrollIntoView({
      behavior: 'smooth',
      block: 'nearest',
      inline: 'center'
    });
  }

  return (
    <>
      <nav>
        <button onClick={() => scrollToIndex(0)}>
          Tom
        </button>
        <button onClick={() => scrollToIndex(1)}>
          Maru
        </button>
        <button onClick={() => scrollToIndex(2)}>
          Jellylorum
        </button>
      </nav>
      <div>
        <ul ref={listRef}>
          <li>
            <img
              src="https://placekitten.com/g/200/200"
              alt="Tom"
            />
          </li>
          <li>
            <img
              src="https://placekitten.com/g/300/200"
              alt="Maru"
            />
          </li>
          <li>
            <img
              src="https://placekitten.com/g/250/200"
              alt="Jellylorum"
            />
          </li>
        </ul>
      </div>
    </>
  );
}
Enter fullscreen mode Exit fullscreen mode

Another use for useRef would be to apply it to a video element so that the video does not re-render every time you hit the play/pause button.

const [isPlaying, setIsPlaying] = useState(false);
  const ref = useRef(null);

  function handleClick() {
    const nextIsPlaying = !isPlaying;
    setIsPlaying(nextIsPlaying);

    if (nextIsPlaying) {
      ref.current.play();
    } else {
      ref.current.pause();
    }
  }

  return (
    <>
      <button onClick={handleClick}>
        {isPlaying ? 'Pause' : 'Play'}
      </button>
      <video
        width="250"
        ref={ref}
        onPlay={() => setIsPlaying(true)}
        onPause={() => setIsPlaying(false)}
      >
        <source
          src="https://interactive-examples.mdn.mozilla.net/media/cc0-videos/flower.mp4"
          type="video/mp4"
        />
      </video>
    </>
  );
}
Enter fullscreen mode Exit fullscreen mode

Some other use cases would be building a stopwatch or creating a click counter.

In conclusion, you should use useRef in React when you need to perform certain tasks that involve managing mutable references to elements or values within your components without causing re-renders.

REFERENCES:
https://react.dev/reference/react/useRef

Top comments (1)

Collapse
 
kenneth_sidibe profile image
Kenneth

Very interesting read !