Introduction
When working with React, useRef
is a powerful hook that allows you to access and persist values across renders without causing re-renders. This makes it an essential tool for handling DOM references, persisting state, and optimizing performance.
This article will break down useRef
, explore its use cases, and demonstrate best practices for using it effectively in TypeScript projects.
Understanding useRef π₯
The useRef
hook is a built-in React hook that returns a mutable object with a .current
property. Unlike state variables created with useState
, modifying useRef
does not trigger re-renders.
Syntax
const ref = useRef<T>(initialValue);
T
is the type of the referenced value.initialValue
is the initial value of.current
.
Example:
import { useRef } from "react";
const inputRef = useRef<HTMLInputElement | null>(null);
Common Use Cases βοΈ
1. Accessing and Manipulating DOM Elements
A frequent use case for useRef
is accessing DOM elements without triggering re-renders.
import { useRef } from "react";
const FocusInput = () => {
const inputRef = useRef<HTMLInputElement>(null);
const handleClick = () => {
inputRef.current?.focus();
};
return (
<div>
<input ref={inputRef} type="text" placeholder="Type something..." />
<button onClick={handleClick}>Focus Input</button>
</div>
);
};
export default FocusInput;
Explanation:
The
inputRef
refers to the<input>
element.Calling
inputRef.current?.focus()
sets focus on the input field.
2. Persisting Values Without Re-Renders
useRef
is useful for persisting values that donβt trigger re-renders, such as timers, previous values, or component lifecycles.
import { useEffect, useRef, useState } from "react";
const Timer = () => {
const [count, setCount] = useState(0);
const intervalRef = useRef<NodeJS.Timeout | null>(null);
useEffect(() => {
intervalRef.current = setInterval(() => {
setCount((prev) => prev + 1);
}, 1000);
return () => {
if (intervalRef.current) clearInterval(intervalRef.current);
};
}, []);
return <p>Timer: {count} seconds</p>;
};
export default Timer;
Explanation:
The
intervalRef
persists the interval ID.It prevents unnecessary re-renders while ensuring the timer can be cleared when needed.
3. Storing Previous Values
We can use useRef
to store the previous state value before a component re-renders.
import { useEffect, useRef, useState } from "react";
const PreviousValue = () => {
const [count, setCount] = useState(0);
const prevCountRef = useRef<number>(count);
useEffect(() => {
prevCountRef.current = count;
}, [count]);
return (
<div>
<p>Current: {count}</p>
<p>Previous: {prevCountRef.current}</p>
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
);
};
export default PreviousValue;
Explanation:
prevCountRef.current
stores the previous count.Even after re-renders, it retains the previous state value.
Best Practices for useRef π―
1- Use useRef
for Non-Rendering Data: Avoid using it for state management that affects UI.
2- Use TypeScript to Ensure Safety: Always define proper types to avoid null
or undefined
errors.
3- Remember That useRef
Doesnβt Trigger Re-Renders: Update .current
only when necessary.
4- Avoid Overuse: If a value needs to trigger a re-render, useState
is the better option.
Conclusion β
The useRef
hook is an essential tool for optimizing React applications. Whether accessing DOM elements, persisting values, or handling timers, it provides performance benefits by preventing unnecessary re-renders.
By combining useRef
with TypeScript, you can write safer and more maintainable React applications.
π Connect With Me On:
π LinkedIn
π X (Twitter)
π Telegram
π Instagram
Happy Coding!
Top comments (0)