What are refs used for in React
Updated Mar 6, 2026
Short answer
Refs are an escape hatch which allow you to get direct access to a DOM element or an instance of a component. In order to use them you add a ref attribute to your component whose value is a callback function which will receive the underlying DOM element or the mounted instance of the component as its first argument.
In React, refs are used to directly access and interact with DOM elements or to persist mutable values across renders without causing re-renders.
They are created using useRef() and are commonly used for:
- Accessing DOM elements (focus, scroll, measurements)
- Storing mutable values (timers, previous values)
- Keeping values that don’t affect UI rendering
Deep explanation
What is a ref?
A ref (reference) is an object that looks like this:
{ current: value }It persists across component re-renders and can be updated without triggering a re-render.
---
Creating a ref
import { useRef } from "react";
function Example() { const inputRef = useRef(null);
return <input ref={inputRef} />;}Here:
inputRef.currentpoints to the actual DOM element
---
Main Uses of Refs
---
1. Accessing DOM elements directly
This is the most common use case.
Example: focusing an input
function App() { const inputRef = useRef(null);
const focusInput = () => { inputRef.current.focus(); };
return ( <> <input ref={inputRef} /> <button onClick={focusInput}>Focus</button> </> );}👉 Used for:
- Focus management
- Scrolling elements
- Measuring DOM size or position
---
2. Storing mutable values (without re-rendering)
Refs can hold values that don’t affect UI.
Example: storing interval ID
function Timer() { const intervalRef = useRef(null);
const start = () => { intervalRef.current = setInterval(() => { console.log("Running..."); }, 1000); };
const stop = () => { clearInterval(intervalRef.current); };}👉 Why use ref?
- Updating it does NOT trigger re-render
- Perfect for non-UI state
---
3. Keeping previous state values
import { useEffect, useRef } from "react";
function Counter({ value }) { const prevValue = useRef();
useEffect(() => { prevValue.current = value; }, [value]);
return ( <div> Current: {value}, Previous: {prevValue.current} </div> );}---
4. Avoiding unnecessary re-renders
If a value does NOT affect UI, using state would cause extra renders. Refs avoid that overhead.
class UnControlledForm extends Component { handleSubmit = () => { console.log("Input Value: ", this.input.value) } render () { return ( <form onSubmit={this.handleSubmit}> <input type='text' ref={(input) => this.input = input} /> <button type='submit'>Submit</button> </form> ) } }
Above notice that our input field has a ref attribute whose value is a function. That function receives the actual DOM element of input which we then put on the instance in order to have access to it inside of the handleSubmit function. It’s often misconstrued that you need to use a class component in order to use refs, but refs can also be used with functional components by leveraging closures in JavaScript.
function CustomForm ({handleSubmit}) { let inputElement return ( <form onSubmit={() => handleSubmit(inputElement.value)}> <input type='text' ref={(input) => inputElement = input} /> <button type='submit'>Submit</button> </form> ) }
Real-world example
Scenario: Video player controls
function VideoPlayer() { const videoRef = useRef(null);
const play = () => videoRef.current.play(); const pause = () => videoRef.current.pause();
return ( <> <video ref={videoRef} src="video.mp4" /> <button onClick={play}>Play</button> <button onClick={pause}>Pause</button> </> );}👉 Why refs are ideal here:
- Direct control of DOM element
- No need for state updates
- Efficient performance
---
When should you use refs?
Use refs when:
- You need direct DOM access
- You want to store values without re-rendering
- You need to persist data across renders
- You are integrating with third-party libraries
---
When NOT to use refs
Avoid refs when:
- The value affects UI rendering → use state instead
- You are managing reactive data flow
- You can solve the problem with props/state
Common mistakes
- ### 1. Using refs instead of state
- ```js id="bad1"
- ref.current = 10
- // ❌ UI will NOT update
- ```
- ---
- ### 2. Expecting re-render on ref change
- Refs do not trigger re-renders.
- ---
- ### 3. Overusing refs for data flow
- Refs should not replace React’s state system.
- ---
- ### 4. Mutating complex objects inside refs
- Can lead to hard-to-track logic if misused.
- ---
- ## Core Idea
- * **State → drives UI**
- * **Refs → store non-UI or direct DOM values**
Follow-up questions
- What is the difference between `useRef` and `useState`?
- When should you prefer refs over state?
- How are refs used in React animations?
- What is `forwardRef` in React?
- Can refs cause memory leaks in React applications?