
React provides a set of powerful Hooks that enable developers to manage state, side effects, and application behavior inside functional components. Among them, useState
and useRef
are foundational tools used in nearly every React application.
While both Hooks allow you to store data across renders, they serve very different purposes. Understanding when to use useRef
instead of useState
, and vice versa, is critical for building efficient, maintainable components.
In this guide, we’ll explore the differences between useRef
and useState
, their internal behavior, practical use cases, and how to determine which one fits best depending on your needs.
What Is useState
?
useState
is a Hook that allows you to introduce reactive state into a functional component. When the state changes using the provided setter function, React automatically re-renders the component so that the UI reflects the latest state.
Example:
import React, { useState } from 'react';
function Counter() {
const [count, setCount] = useState(0);
return <button onClick={() => setCount(count + 1)}>Count: {count}</button>;
}
In this example:
count
holds the current state.setCount
updates the state.- Updating
count
causes a re-render.
What Is useRef
?
useRef
is a Hook that returns a mutable object which persists for the full lifetime of the component. It is primarily used for:
- Accessing or modifying DOM elements directly.
- Storing non-reactive mutable data.
- Tracking values between renders without causing re-renders.
Example:
import React, { useRef } from 'react';
function TextInput() {
const inputRef = useRef(null);
const handleFocus = () => {
inputRef.current.focus();
};
return (
<>
<input ref={inputRef} />
<button onClick={handleFocus}>Focus</button>
</>
);
}
Here, inputRef.current
holds the reference to the DOM input element. Changing this value will not trigger a re-render.
Key Differences Between useState
and useRef
Feature | useState | useRef |
---|---|---|
Triggers component re-render on update | Yes | No |
Value persists across re-renders | Yes | Yes |
Designed for UI state | Yes | No |
Ideal for storing mutable values | No | Yes |
Can reference DOM elements | No | Yes |
Access method | Setter function | .current property |
Reactive | Yes | No |
When Should You Use useState
?
1. Managing Values That Affect Rendering
If the variable is used in JSX or determines what gets rendered, use useState
.
const [isVisible, setIsVisible] = useState(false);
This updates the DOM to show or hide content based on the value.
2. Tracking Controlled Input Fields
For controlled forms, where input fields are tied to component state:const [username, setUsername] = useState('');
<input value={username} onChange={(e) => setUsername(e.target.value)} />
3. Implementing UI Logic and Conditional Rendering
Use useState
for toggles, modals, dynamic classes, or conditional elements.
{isDarkMode ? <DarkTheme /> : <LightTheme />}
When Should You Use useRef
?
1. Accessing and Manipulating DOM Elements
useRef
is ideal for working with DOM APIs in a declarative React environment.
const inputRef = useRef(null);
useEffect(() => {
inputRef.current.focus();
}, []);
2. Persisting Mutable Data That Does Not Affect Rendering
If you need to persist data without re-rendering (e.g., timer IDs, scroll positions, cached data), useRef
is the correct choice.
const timeoutId = useRef(null);
3. Tracking Render Counts or Previous Values
useRef
allows you to keep values between renders without reacting to them.const renderCount = useRef(1);
useEffect(() => {
renderCount.current += 1;
});
4. Avoiding Unnecessary Re-renders
If you are updating a value that does not impact the visual output of the component, use useRef
to avoid performance overhead.
const debounceTimer = useRef(null);
Common Mistakes to Avoid
Mistake: Using useRef
for Values That Control the UI
const inputValue = useRef('');
<input value={inputValue.current} />
Why it’s wrong: Updating .current
does not trigger a re-render, so the input will not behave as expected.
Correct approach:
const [inputValue, setInputValue] = useState('');
Mistake: Using useState
for Data That Doesn’t Impact the UI
const [timerId, setTimerId] = useState(null);
This is inefficient if the timer ID is not used in rendering.
Better approach:
const timerId = useRef(null);
How to Choose Between useState
and useRef
Ask yourself the following:
- Does the value control what appears in the UI?
→ Yes → UseuseState
- Is the value only used internally (e.g., a reference, cache, timer)?
→ Yes → UseuseRef
- Will updating the value require a re-render for UI changes to be visible?
→ Yes → UseuseState
- Do you need to manipulate a DOM node directly?
→ Yes → UseuseRef
Real-World Use Case Summary
Scenario | Hook to Use | Explanation |
---|---|---|
Toggling a modal | useState | The modal is part of the UI |
Tracking scroll position | useRef | Value is not rendered |
Controlled form input | useState | Input must reflect in real time |
Debounce timer for search input | useRef | No UI update required |
Accessing a DOM input to focus | useRef | Direct DOM manipulation |
Displaying loading/error states | useState | Affects rendering of loading indicators |
Final Thoughts
Both useState
and useRef
are indispensable tools in the React ecosystem, but they are designed for different responsibilities.
- Use
useState
when your value needs to trigger a re-render and impact the UI. - Use
useRef
when you need to persist data across renders without triggering updates to the component’s output.
Mastering the correct usage of these two Hooks leads to better performance, more predictable behavior, and cleaner component logic. As your React applications grow, your ability to distinguish when to use useRef
and useState
will be a key part of writing scalable, maintainable code.

I’m Shreyash Mhashilkar, an IT professional who loves building user-friendly, scalable digital solutions. Outside of coding, I enjoy researching new places, learning about different cultures, and exploring how technology shapes the way we live and travel. I share my experiences and discoveries to help others explore new places, cultures, and ideas with curiosity and enthusiasm.