React useRef Hook Explained for Beginners (Examples)
What is useRef in React? Learn what a ref is, how it differs from useState, and how to focus an input, with short copy-paste examples for beginners.
What is useRef in React? Learn what a ref is, how it differs from useState, and how to focus an input, with short copy-paste examples for beginners.
What is useRef in React? In plain words, useRef is a React hook that gives you a box to keep a value in. The box survives every re-render, and changing what is inside it does not redraw your screen. People mostly use it for two jobs: grabbing an element on the page (like focusing an input) and remembering a value without causing a re-render.
This guide is for absolute beginners. We define each new word, and every example is short enough to copy and run. If you have not met hooks yet, read our guide on React hooks first, then come back.
A ref (short for reference) is a plain object that React keeps for you. It always has one property, called current. You can put anything in current: a number, a string, or a page element.
A hook is a special React function whose name starts with use. It lets a component use React features. useRef is one of these hooks.
import { useRef } from 'react';
function Demo() {
const countRef = useRef(0);
console.log(countRef.current); // 0
return <p>Hello</p>;
}Line 1 imports the hook. Line 4 creates a ref and starts it with the value 0. Line 5 reads the value from countRef.current. The ref object itself is the same one every time the component runs.
Both remember a value between renders. A render is when React runs your component to draw it on screen. The big difference is what happens when the value changes.
| useState | useRef | |
|---|---|---|
| Remembers value between renders | Yes | Yes |
| Changing it re-renders the component | Yes | No |
| How you change it | Call the setter function | Write to ref.current |
| Best for | Anything shown on screen | Elements and hidden values |
A simple rule: if the user should see the value on screen, use useState. If you only need to remember it behind the scenes, use useRef.
The most common use is reaching a page element directly. Here we make a button that puts the cursor inside a text box.
import { useRef } from 'react';
function FocusInput() {
const inputRef = useRef(null);
function handleClick() {
inputRef.current.focus();
}
return (
<div>
<input ref={inputRef} type="text" />
<button onClick={handleClick}>Focus the input</button>
</div>
);
}Line 4 makes a ref that starts as null, because the input does not exist yet. On the input, ref={inputRef} tells React: once you create this element, store it in inputRef.current. In handleClick, inputRef.current is the real input element, so we can call the browser method focus() on it. Click the button and the cursor jumps into the box.
You can combine useRef with useEffect, a hook that runs code after the component appears. This focuses the input automatically.
import { useEffect, useRef } from 'react';
function SearchBox() {
const inputRef = useRef(null);
useEffect(() => {
inputRef.current.focus();
}, []);
return <input ref={inputRef} placeholder="Search..." />;
}The empty array [] on line 8 means the effect runs only once, right after the first render. By then the input exists, so inputRef.current is ready to use.
Refs can also hold ordinary values. Let us count how many times a button was clicked without redrawing the page each time.
import { useRef } from 'react';
function ClickCounter() {
const clicks = useRef(0);
function handleClick() {
clicks.current = clicks.current + 1;
console.log('Clicked ' + clicks.current + ' times');
}
return <button onClick={handleClick}>Click me</button>;
}Each click adds 1 to clicks.current and prints the total in the browser console. The number is remembered, but the screen does not update. If you want to show the count on screen, switch to useState.
import { useRef } from 'react';
function NameForm() {
const nameRef = useRef(null);
function handleSubmit(event) {
event.preventDefault();
alert('Hello, ' + nameRef.current.value);
}
return (
<form onSubmit={handleSubmit}>
<input ref={nameRef} type="text" />
<button type="submit">Say hello</button>
</form>
);
}preventDefault() stops the browser from reloading the page. Then nameRef.current.value reads whatever the user typed. This is called an uncontrolled input, because React does not track each keystroke. For most forms, beginners are better off with controlled inputs using useState.
useRef creates an object with a current property that React keeps the same across renders. You can store an element or any value in it. Changing current does not re-render the component.
useState triggers a re-render when you change the value, so the screen updates. useRef does not trigger a re-render. Use useState for things users see and useRef for things you only need to remember.
The element has not been created yet. During the first render the ref is empty. Read it inside an event handler or a useEffect, which run after the element appears.
Yes. Any value works, such as a number, a string, or a timer ID. The value stays between renders and changing it does not redraw the page.
Usually no. Controlled inputs with useState are the standard way and are easier to validate. Refs are fine for simple cases like reading a value on submit.
New to state? Read our beginner guide to the useState hook to see how it differs from refs.
Read the useState guideWant help building your first React app? Talk to the Fepiq team.
Get in touchOccasional, no-fluff notes on shipping modern software — startups, automation, Laravel, Shopify and more. No spam, unsubscribe anytime.
Keep reading
Learn SQL CASE WHEN step by step. This beginner guide shows how to label, group and sort data with simple examples you can copy and run today.
PostgreSQL ILIKE explained for beginners: search text without worrying about case, learn % and _ wildcards, and copy simple examples you can run today.
Let's build something
Book a free discovery call. We'll listen, ask sharp questions, and send you a proposal within 3 business days.