The useRef
hook in React is used to directly reference DOM elements or persist mutable values without causing re-renders. It is an incredibly useful tool for scenarios where you need to interact with the DOM or retain a mutable state across renders.
When to Use useRef
- Accessing DOM Elements: Directly manipulate or access a DOM element (e.g., focusing an input, scrolling).
- Storing Mutable Data: Retain values (like timers, IDs, or previous states) without triggering re-renders.
- Keeping Previous Values: Store the previous value of props or state for comparison.
Syntax
const refContainer = useRef(initialValue);
refContainer
: An object with acurrent
property where the value is stored.initialValue
: The initial value to be assigned to thecurrent
property.
Example 1: Accessing a DOM Element
Code Example: Focus on an Input Field
import React, { useRef } from "react"; function FocusInput() { const inputRef = useRef(null); const handleFocus = () => { inputRef.current.focus(); // Focus the input field }; return ( <div> <input type="text" ref={inputRef} placeholder="Enter text" /> <button onClick={handleFocus}>Focus Input</button> </div> ); } export default FocusInput;
- Explanation:
useRef
creates a reference to the input element.- The
current
property of the reference is used to call thefocus
method.
Example 2: Persisting Mutable Values
Code Example: Store Timer Value
import React, { useRef, useState } from "react"; function Timer() { const [seconds, setSeconds] = useState(0); const timerRef = useRef(null); const startTimer = () => { if (!timerRef.current) { timerRef.current = setInterval(() => { setSeconds((prev) => prev + 1); }, 1000); } }; const stopTimer = () => { clearInterval(timerRef.current); timerRef.current = null; }; return ( <div> <p>Timer: {seconds} seconds</p> <button onClick={startTimer}>Start</button> <button onClick={stopTimer}>Stop</button> </div> ); } export default Timer;
- Explanation:
timerRef
holds the timer ID.- Since
useRef
doesn’t trigger re-renders, the timer logic remains efficient.
Example 3: Storing Previous State
Code Example: Previous Value Comparison
import React, { useRef, useEffect, useState } from "react"; function PreviousValueExample() { const [count, setCount] = useState(0); const prevCount = useRef(null); useEffect(() => { prevCount.current = count; // Update the previous value }); return ( <div> <p>Current Count: {count}</p> <p>Previous Count: {prevCount.current}</p> <button onClick={() => setCount((prev) => prev + 1)}>Increment</button> </div> ); } export default PreviousValueExample;
- Explanation:
- The
prevCount
ref stores the count value from the previous render. - It doesn’t cause a re-render when updated.
- The
Example 4: Managing Animations
Code Example: Smooth Scrolling
import React, { useRef } from "react"; function SmoothScroll() { const divRef = useRef(null); const scrollToBottom = () => { divRef.current.scrollIntoView({ behavior: "smooth" }); }; return ( <div> <div style={{ height: "500px", overflow: "auto", border: "1px solid black" }}> <div style={{ height: "1000px" }}>Scroll Down</div> <div ref={divRef}>You’ve reached the bottom!</div> </div> <button onClick={scrollToBottom}>Scroll to Bottom</button> </div> ); } export default SmoothScroll;
- Explanation:
useRef
targets a specific DOM element.- The
scrollIntoView
method is triggered for smooth scrolling.
Key Points About useRef
- Does Not Trigger Re-Renders: Updating the
.current
property doesn’t re-render the component. - Persistent Across Renders: The value persists between renders, unlike local variables inside the function.
- Avoid Overuse: Use
useRef
primarily for DOM manipulation or storing non-reactive data.
Common Mistakes with useRef
- Misusing for State: Don’t use
useRef
for values that need to trigger re-renders. UseuseState
instead. - Unnecessary Updates: Avoid frequent updates to
current
when it isn’t necessary. - Improper Initial Value: Ensure the
initialValue
matches the type of data you plan to store.
Best Practices
- Use
useRef
for accessing or modifying DOM elements directly. - Combine with
useEffect
for side effects that involve the DOM. - For better readability, encapsulate logic involving
useRef
in custom hooks when reused frequently.
useRef
is a lightweight and powerful tool for managing mutable references, making it invaluable for specific scenarios in React development.