Home
React
React Hook: useRef()
Daniel Nguyen
Daniel Nguyen
July 10, 2025
1 min

Sometimes, React state isn’t enough. You may need direct access to a DOM element, such as focusing an input, managing a video, or integrating a third-party library.

useRef provides a persistent object that survives re-renders without triggering a re-render when its .current property changes.

1. Accessing the DOM

Attach a ref to a DOM element to access it directly.

import { useRef } from "react";
function SearchInput() {
const inputRef = useRef(null);
const handleFocus = () => {
inputRef.current?.focus();
};
return (
<>
<input ref={inputRef} />
<button onClick={handleFocus}>Focus</button>
</>
);
}

Clicking the button focuses the input without requiring state.

2. Integrating Third-Party Libraries

Refs are useful when a library manages its own DOM elements or rendering lifecycle.

import { useEffect, useRef } from "react";
function Chart() {
const containerRef = useRef(null);
useEffect(() => {
const chart = createChart(containerRef.current);
return () => chart.destroy();
}, []);
return <div ref={containerRef} />;
}

The ref provides the DOM container, while the cleanup function destroys the chart when the effect is no longer needed.

3. Avoid Overusing useRef

It doesn’t trigger re-renders

Unlike state, changing ref.current doesn’t tell React to update the UI.

inputRef.current.value = "Hello";

This directly changes the DOM input value. React doesn’t track this change as state, so prefer controlled inputs when the value needs to stay synchronized with React.

It can make debugging harder

Ref mutations aren’t tracked as state updates in React DevTools. Overusing refs to store UI-related data can make behavior harder to understand and maintain.

Rule of thumb: Use state for data that affects rendering and refs for values that need to persist without triggering a re-render.

4. Primitive Dependencies

React compares effect dependencies using Object.is. Primitive values such as strings, numbers, and booleans are often convenient dependencies because their identity is determined by their value.

const userId = user.id;
useEffect(() => {
fetchUser(userId);
}, [userId]);

The effect re-runs when userId changes.

By contrast, objects and arrays can have new references even when their contents are equivalent.

const options = { active: true };
useEffect(() => {
connect(options);
}, [options]);

Because options is recreated on every render, the effect may re-run unnecessarily. When possible, depend on the specific primitive values the effect needs or create the object inside the effect.


Tags

#ReactHook

Share

Daniel Nguyen

Daniel Nguyen

Frontend Developer

Frontend developer specializing in React, Next.js, and JavaScript. Writing practical guides on modern web development at Dev98.

Expertise

React
Next.js
JavaScript
TypeScript
Python

Social Media

githublinkedinyoutubewebsite

Related Posts

React Hook
React Hook: useId()
July 09, 2025
1 min
Dev98

Dev98

React · Next.js · Web development