Nearby lessons

18 of 44

🪝 ReactJS – useRef Hook & Uncontrolled Components

📌 What is useRef?

What is useRef Hook in React?

The useRef Hook allows you to persist values between renders without causing re-renders. It can also be used to directly access DOM elements in functional components. An uncontrolled component uses refs instead of state to manage form inputs.

📌 Why use useRef?

  • Access DOM elements directly using ref attribute
  • Store a mutable value that does not cause re-render
  • Persist values across component renders
  • Helpful for uncontrolled components (like forms without state)

⚙️ Accessing DOM Elements with useRef

We can attach a ref to any element to access it directly in the DOM.

Here, we use useRef with <h1> and change its style dynamically.

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

const UseRefHook = () => {
  const newRef = useRef();

  useEffect(() => {
    console.log(newRef);
    console.log(newRef.current);
  });

  const handleHeading = () => {
    newRef.current.style.color = "red";
    newRef.current.style.fontFamily = "cooper";
  }

  return (
    <div>
      <h1 ref={newRef}>Learning Never Ends</h1>
      <button onClick={handleHeading}>Click</button>
    </div>
  )
}

export default UseRefHook;

📝 Uncontrolled Component with useRef

Instead of storing form values in useState, we can use useRef to directly read values from input fields.

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

const UseRefHook = () => {
  const firstRef = useRef();
  const lastRef = useRef();

  useEffect(() => {
    firstRef.current.focus();
    firstRef.current.style.color = "red";
    firstRef.current.style.backgroundColor = "green";
  });

  const handleSubmit = (e) => {
    e.preventDefault();
    console.log('Full Name = ', firstRef.current.value, lastRef.current.value);
  }

  return (
    <form onSubmit={handleSubmit}>
      <label>First Name</label>
      <input type="text" ref={firstRef} placeholder="Enter First Name" /> <br /><br />
      <label>Last Name</label>
      <input type="text" ref={lastRef} placeholder="Enter Last Name" /> <br /><br />
      <input type="submit" value="Submit" />
    </form>
  )
}

export default UseRefHook;

❌ Problem: Using useState for Render Count

If we try to use useState inside useEffect to count renders, it causes an infinite loop.

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

const UseRefHook2 = () => {
  const [inputValue, setInputValue] = useState("");
  const [count, setCount] = useState(0);

  useEffect(() => {
    setCount(count + 1); // ❌ Causes re-render loop
  }, []);

  return (
    <div>
      <label>Enter Name: </label>
      <input 
        type="text"
        value={inputValue}
        onChange={(e) => setInputValue(e.target.value)} 
      />
      <h2>Render count: {count}</h2>
    </div>
  )
}

export default UseRefHook2;

✅ Solution: Using useRef for Render Count

We can fix this issue by using useRef instead of useState since updating ref.current does not trigger re-renders.

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

const UseRefHook2 = () => {
  const [inputValue, setInputValue] = useState("");
  const count = useRef(0);

  useEffect(() => {
    count.current = count.current + 1;
  });

  return (
    <div>
      <label>Enter Name: </label>
      <input 
        type="text"
        value={inputValue}
        onChange={(e) => setInputValue(e.target.value)} 
      />
      <h2>Render count: {count.current}</h2>
      <h3>Name: {inputValue}</h3>
    </div>
  )
}

export default UseRefHook2;

🧠 Test Your Knowledge

3 Questions

Progress: 0 / 3
Keep Going!React - useContext Hook