What is useRef Hooks Everything You Need to Know
If you’re looking for a way to keep track of and manage references in your React application, you should consider using useRef hooks.
DOM manipulation is the heart of modern, interactive web development.
In Vanilla Javascript, imperative manipulation of the DOM is straight forward.
where you have to select a DOM node element using document.getElementById(), getElementsByName(), getElementsByTagName(), getElementsByClassName() or querySelector().
const element = document.getElementById(id);
Then modify or store it in a variable for later reference of the selected elements and their attributes.
But React is said to be declarative. It updates the DOM using a Virtual DOM, to match your render output. Your components won't often need to manipulate the DOM.
With the introduction of the useRef hook, React provides a way to access the DOM nodes of elements created in the render() method.
You Will Learn
- What useRef is about
- When to useRefs
- When !to useRefs
- Difference Between Ref and State
- Adding a useRef hook to your component
- Use case of useRef
First of all, we need to understand what the DOM, DOM trees and Virtual DOM are.
The DOM
Document Object Model is an application interface (API) for HTML and XML documents. It defines the logical structure of documents and the way a document is accessed and manipulated.
DOM Tree
A DOM tree is more like a real life tree whose nodes (branches) represent an HTML or XML document's contents..
The Virtual DOM
In React, for every DOM node, there is a corresponding "Virtual DOM" (VDOM aka Vnode). A virtual DOM is a representation of a DOM object, like a lightweight copy of the DOM (copy DOM).
Virtual DOM is a programming concept, where an exact representation of the UI is kept in memory and synchronised with the real DOM.
This is a declarative programming style, where you tell React's virtual DOM what state you want the UI to be. And it makes sure the real DOM matches that state.
This abstracts out the chance to manipulate and handle events in the DOM manually.
What useRef is about
React has a hook -useRef which provides a way to access DOM nodes or React JSX elements created in the render methods.
useRef hook returns an object
const numberRef = useRef();
console.log(numberRef); //{current: 0}
This object is mutable.
This means it can be read and modified; Hence the returned .current property here can be updated.
The ref object exists outside of React's render cycle. Any value stored here remains available throughout a component lifecycle.
The react virtual DOM doesn't re-render when the ref value is updated.
Another important feature of the useRef hook is that it provides a way for developers to interact directly with DOM nodes, outside of Reacts management (outside of the Virtual DOM).
React describes this as an "escape hatch"
When to useRefs
- Manage input focus, text selection or media playback
- Trigger Imperative animations
- To Stores timeout IDs of infrastructure data
- To Store values that aren't necessary to calculate the JSX render output
- To Integrate third-party DOM libraries
When !to useRef
When not to useRef
- Avoid using refs for anything that can be done declaratively (Don't overuse the useRef hook)
- Don't read or write ref.current during rendering. If a value is needed during rendering, useState instead.
Difference Between Ref and State
refs | state |
useRef Doesn’t trigger re-render when you change it. | Components re-render when you change state. |
You shouldn’t read (or write) the .current value during rendering | You can read state at any time. |
When a piece of information is only needed by event handlers and changing it doesn’t require a re-render, using a ref may be more efficient | When a piece of information is used for rendering, keep it in state |
Reference update is synchronous (the updated reference value is available right away). This is because the ref itself is a regular JavaScript object, and so it behaves like one. | While State update is asynchronous (the state variable is updated after re-rendering). |
Adding a useRef hook to your component
useRef can be added to a React component by importing the useRef hook from react.
import {useRef} from "react";
Inside the react component, call and initialize the useRef. Give it an argument as its initial value.
const ref = useRef(0);
useRef returns an object
{
current : 0 //value passed to useRef
}
You can access the current value of the ref using ref.current property. This value is mutable.
Use Case
✔ To Store Mutable Value
There are a few ways to use the useRef hook in React.
One way is to use it to store a reference.
The useRef hook is a function that creates a mutable object that persists throughout a component's lifecycle. It holds a mutable value in its .current property.
useRef(initialValue) is a built-in react hook that accepts an argument as the initial value and returns a reference(ref).
A reference is an object with the special property current, which can be read or modified.
import {useRef} from "react";
function MyComponent () {
const reference = useRef(initialValue);
const someHandler = () => {
//Access reference value
const value = refernce.current
//update reference value
reference.current = newValue;
}
}
In the code above the reference.current gives access to the stored reference value.
When we reference (store) a value using useRef
- The current value of the reference is persistent
- Updating ref doesn't trigger a component rendering
Here’s an example of useRef that increments its referenced value on every click of a button
import { useRef } from "react";
export default function LogButton() {
const countRef = useRef(0);
const handle = () => {
//update reference value
countRef.current++;
alert("You clicked " + countRef.current + " times!");
};
//component renders just once
console.log("I rendered");
return (
<>
<button onClick={handle}>Click Me</button>
</>
);
}
useRef prompts the number of clicks on the button.
On every click, the countRef.current value is increased and prompted on the browser alert.
And the console.log() is only rendered once. This Shows the component doesn't re-render on every click and update of the ref value.
✔ To Access DOM element
One of the most common use case of useRef is to access the DOM element.
It can be used to access the current property of a DOM element, autofocus on an Input form, scroll to an element position, and other DOM manipulations.
◾ Access the current property of an Element
import { useRef, useEffect } from "react";
export default function DomAccess() {
const elementRef = useRef();
useEffect(() => {
const divElement = elementRef.current;
console.log(divElement);
}, []);
return <div ref={elementRef}>I'm a Div Element</div>;
}
Accessing the DOM element can be broken down into 3 steps.
Steps
- Declare the reference
const elementRef = useRef()
- Assign the declared reference to an element using the HTML ref attribute.
<div ref={elementRef}>Element </div>
- use useEffect hook, on mount this immediately assigns the elementRef.current to the variable divElement.
useEffect(() => { const divElement = elementRef.current; console.log(divElement); }, []);
◾ Auto-Focus On Input
DOM elements need to be accessed.
In other, to focus on an input form field in a browser when the component mounts.
To do this the useRef can be used to call the special focus() attribute on the element.
import { useRef, useEffect } from "react";
export default function FocusInput() {
const inputRef = useRef();
useEffect(() => {
// Logs `HTMLInputElement`
console.log(inputRef.current); //<input type="text"></input>
//auto focus on component render
inputRef.current.focus();
}, []);
// Logs `undefined` during initial rendering
console.log( inputRef.current); //undefined
return <input ref={inputRef} type="text" />;
}
This code uses a ref to store reference to a DOM node element, and then calls a .focus() on the element.
useRef initial value here is undefined during initial rendering.
During the first rendering, the DOM nodes have not been created yet, hence the ref.current will initially return undefined
◾ Scroll to an element
Quite often, you have to scroll a web page to find and skim through its content. However, scrolling endless feeds can be intimidating for users and a bad UX practice.
A common solution is to create a table of contents.
useRef hook in React, offers a better way to achieve the same result. You can refer to an element by using its ref attribute to scroll to it, either automatically or by the click of a button.
This makes the website or app user friendly.
Here to implement this we make use of the useRef hook and the Element.scrollIntoView() method provided by HTML element interface.
developer.mozilla.org/en-US/docs/Web/API/El..
element.scrollIntoView() This method works by scrolling the parent container to the element on which scrollIntoView(), is called on.
This makes the element visible to the user.
scrollIntoView() accepts one argument. It can either be an alignToTop or Options
function TestComponent() {
const testRef = useRef(null);
const scrollToElement = () => testRef.current.scrollIntoView({
//Option object has three optional properties: behaviour, block, inline
behavior: "smooth",
block: "nearest",
inline: "center"
});
return (
<>
<div ref={testRef}>Element you want to view</div>
<button onClick={scrollToElement}>Trigger the scroll</button>
</>
);
}
In the code example above the scrollIntoView() is called on the .current property of the reference element.
This makes the web page scroll, to the referenced element position.
The .currently property only becomes accessible when the component mounts.
Conclusion
useRefs is an escape hatch in the React framework.
Remember to use refs only when there is an implicit function call, they can be used to store any infrastructural data
But not to store data that is to be rendered. Make sure it doesn't alter the internal state of the components.
So now I am curious, which react hook do you use the most, and on what occasion have you picked to use the useRef hook and Why?