skip to Main Content

I’ve been working with React, and I’m trying to understand the difference between creating a reference using useRef and creating a reference without it. I’ve implemented two versions of a simple counter app with a button. In the first version, I create a reference object manually without useRef, while in the second version, I use useRef to create the reference.

Need clarification from community :

  1. Are there specific reasons why we should use useRef over a simple JavaScript object?
  2. How does useRef benefit us in a React component?

Reference without useRef

import { useEffect, useState } from "react";
const REF = { current: undefined };

function App() {
    const [count, setCount] = useState(0);
    useEffect(() => {
        console.log(REF);
    }, [count]);

    return (
        <>
            <h1>{count}</h1>
            <button
                ref={REF}
                onClick={() => setCount((c) => c + 1)}
            >
                +
            </button>
        </>
    );
}

Reference with useRef

function App() {
    const [count, setCount] = useState(0);
    const REF = useRef();
    useEffect(() => {
        console.log(REF);
    }, [count]);

    return (
        <>
            <h1>{count}</h1>
            <button
                ref={REF}
                onClick={() => setCount((c) => c + 1)}
            >
                +
            </button>
        </>
    );
}

2

Answers


  1. Well, useRef is a hook in React for functional components. It has function that provides a mutable reference to a DOM element.
    Creating a ref without useRef just uses the React.createRef() method.
    The typical difference between them is that we normal use useRef hook for the functional component and the Creating a ref without useRef for the class component.
    And the second difference is that createRef method creates a new ref object each time the component re-renders but the useRef hook only returns the same ref object through the component’s lifecycle so doesn’t need the re-render.
    I think the benefit of useRef is that it can have any mutable value without causing a re-renders unlike the createRef method.

    Login or Signup to reply.
  2. The fundamental difference is this : Reference without useRef does not survive renders, but Reference with useRef does survive renders.

    Please see below a sample code which demoes the same.

    App.js

    import { useEffect, useRef, useState } from 'react';
    
    export default function App() {
      const [forceRender, setForceRender] = useState(null);
      let refByUseRef = useRef(0);
      let refPlainObject = { current: 0 };
    
      useEffect(() => {
        console.log(`New State value : ${forceRender}`);
        console.log(`value of refByUseRef.current ${refByUseRef.current}`);
        console.log(`value of refPlainObject.current ${refPlainObject.current}`);
      });
    
      function handleClick() {
        refByUseRef.current++;
        refPlainObject.current++;
        setForceRender(Math.random());
      }
    
      return (
        <button onClick={handleClick}>
          Change Refs and Force a render, then Check comsole logs
        </button>
      );
    }
    

    Test run / Console logs

    Console logs created on initial render as well as on clicking the button two times

    // New State value : null
    // value of refByUseRef.current 0
    // value of refPlainObject.current 0
    
    // New State value : 0.17364783672210882
    // value of refByUseRef.current 1
    // value of refPlainObject.current 0
    
    // New State value : 0.36704460799050587
    // value of refByUseRef.current 2
    // value of refPlainObject.current 0
    

    As we know there are three renders occurred for the component including the initial render. Please look at the code in handleclick. It increments all three variables by one. Now on every single click, there is a render happens, since the state has been changed here.

    Now, the console log makes it confirmed that the variable refPlainObject does not survive the renders since it always reset to 0. However the variable refByUseRef does survive the renders, since its value has changed, each click added its value to its previous value.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search