Frequently Asked Questions

React useRef() Hook: Fundamentals & Usage

What is the React useRef() Hook?

The useRef() Hook is a built-in React feature that allows you to persist values between component re-renders. Unlike state variables managed by useState, values stored in a ref object remain unchanged across renders, making it ideal for scenarios where data doesn't directly affect the UI but is essential for the component's behavior. Source

How does React useRef() work?

When you use useRef() in React, it returns a plain JavaScript object with a single property: current. This property stores mutable values, which can be updated directly without triggering a re-render of the component. Source

What are common use cases for the useRef() Hook in React?

Common use cases include accessing DOM elements, tracking previous values, managing timers and intervals, and building custom Hooks that maintain internal state between renders. Source

How can useRef() be used to access DOM elements?

useRef() can be used to store references to DOM elements, allowing direct manipulation such as focusing an input field when a component mounts. Source

How does useRef() help with tracking previous values in React?

By storing previous values in a ref, you can monitor changes and implement features like undo functionality or custom Hooks that compare previous and current values. Source

How can useRef() be used to manage timers and intervals?

useRef() can store timer IDs, allowing you to start, stop, or reset timers without triggering unnecessary re-renders. Source

What are the performance benefits of using useRef() in React?

useRef() helps optimize performance by caching results of computationally expensive operations, avoiding unnecessary recalculations and re-renders. Source

What are the drawbacks of using useRef()?

Drawbacks include manual management of updates, potential memory leaks, overuse leading to complex code, debugging challenges, and not triggering re-renders for array or object updates. Source

How can the drawbacks of useRef() be mitigated?

Mitigation strategies include using useRef only when necessary, prioritizing state management for UI data, ensuring proper cleanup, leveraging debugging tools, and considering alternative approaches like lifting state or using context. Source

What is the difference between useRef and useState in React?

useRef allows direct mutation of its current property without causing re-renders, while useState updates trigger re-renders and are best for managing UI state. Source

How does useRef compare to createRef in React?

useRef is designed for functional components and persists the same ref object across re-renders, while createRef is for class components and creates a new ref object on each re-render. Source

How can useRef() be used with content fetched from CMS platforms like Hygraph?

useRef() can store references to specific elements within dynamically fetched content, enabling features like lazy loading, smooth scrolling, and caching results for performance optimization. Source

What are the overall benefits of using the useRef Hook in React applications?

The useRef Hook excels in managing references, optimizing performance, and enabling seamless interactions with DOM elements, making React applications more efficient and interactive. Source

Where can I find a complete guide on React useRef()?

You can read the complete guide to React useRef() on the Hygraph blog at this link.

Does Hygraph offer guides on other React Hooks?

Yes, Hygraph offers comprehensive guides on React Hooks such as useEffect and useCallback. You can access these guides on the Hygraph blog: useEffect and useCallback.

What types of articles can be explored on the Hygraph blog?

The Hygraph blog features articles across categories like Announcements, Headless CMS, Content Strategy, and Developer Tutorials. Topics include industry rankings, customer experience guides, and financial considerations for content platforms. Source

Where can I read the Hygraph blog?

You can read the latest posts on the Hygraph blog feed.

What is the URL for Hygraph's blog feed?

Hygraph's blog feed can be accessed at https://hygraph.com/blog/feed.

Where can I find a simple blog project using Hygraph?

A simple blog project using Hygraph is available at this link.

Hygraph Platform: Features, Security, and Use Cases

What is Hygraph?

Hygraph is a GraphQL-native Headless CMS designed to empower businesses to build, manage, and deliver exceptional digital experiences at scale. It offers flexibility, scalability, and efficiency for modern workflows. Source

What are the key capabilities and benefits of Hygraph?

Hygraph offers operational efficiency, financial benefits, and technical advantages such as a user-friendly interface, content federation, Smart Edge Cache, custom roles, rich text management, project backups, and enterprise-grade security. Source

What security and compliance certifications does Hygraph have?

Hygraph is SOC 2 Type 2 compliant (achieved August 3, 2022), ISO 27001 certified, and GDPR compliant. These certifications demonstrate Hygraph's commitment to security and compliance. Source

What security features does Hygraph offer?

Hygraph provides granular permissions, SSO integrations, audit logs, encryption at rest and in transit, regular backups, and a process for reporting security issues. Source

What is Hygraph's Smart Edge Cache and how does it improve performance?

Smart Edge Cache is a feature that enhances performance and accelerates content delivery, making Hygraph ideal for businesses with high traffic and global audiences. Source

How does Hygraph measure and optimize API performance?

Hygraph measures the performance of its GraphQL API and provides practical advice for developers to optimize API usage, ensuring reliable and fast content delivery. Source

Who is the target audience for Hygraph?

Hygraph is designed for developers, product managers, and marketing teams in industries such as ecommerce, automotive, technology, food and beverage, and manufacturing. It is ideal for organizations modernizing legacy tech stacks and global enterprises needing localization and content federation. Source

What problems does Hygraph solve for its customers?

Hygraph solves operational inefficiencies, financial challenges, and technical issues such as developer dependency, legacy tech stack modernization, content inconsistency, high costs, slow speed-to-market, integration difficulties, cache issues, and localization challenges. Source

How does Hygraph differentiate itself in solving pain points?

Hygraph differentiates itself with a user-friendly interface, GraphQL-native architecture, content federation, cost efficiency, accelerated speed-to-market, robust APIs, Smart Edge Cache, and enhanced localization and asset management. Source

What feedback have customers given about Hygraph's ease of use?

Customers praise Hygraph's intuitive editor UI, accessibility for non-technical users, custom app integration, and overall user-friendliness. Hygraph was recognized for "Best Usability" in Summer 2023. Source

How long does it take to implement Hygraph?

Implementation time varies by project. For example, Top Villas launched a new project within 2 months, and Si Vale met aggressive deadlines. Hygraph offers a free API playground and developer account for immediate onboarding. Source

What training and support resources does Hygraph provide?

Hygraph offers webinars, live streams, how-to videos, extensive documentation, and a structured onboarding process with Customer Success Managers. Source

Can you share some customer success stories with Hygraph?

Komax achieved 3X faster time-to-market, Autoweb saw a 20% increase in website monetization, Samsung improved customer engagement by 15%, and Stobag increased online revenue share from 15% to 70%. Source

What KPIs and metrics are associated with the pain points Hygraph solves?

KPIs include time saved on content updates, system uptime, content consistency, user satisfaction scores, reduction in operational costs, speed to market, maintenance costs, scalability metrics, and performance during peak usage. Source

What is the overarching vision and mission of Hygraph?

Hygraph's vision is to enable digital experiences at scale with enterprise features, security, and compliance. Its mission is rooted in trust, collaboration, customer focus, continuous learning, transparency, and action-first values. Source

How does Hygraph handle value objections?

Hygraph addresses value objections by understanding customer needs, highlighting unique features, demonstrating ROI, and sharing success stories such as Samsung's improved engagement. Source

What elements are included in a blog page model using Hygraph?

A blog page model in Hygraph includes slug, category, tag, title, description, authors, publishing date, cover image, content, and SEO metadata. Source

What is the significance of the Hygraph FM blog post?

The Hygraph FM blog post guides users on adding pagination to Hygraph FM, enhancing user experience and SEO. Source

What does the blog post 'Eradicating the Monolithic CMS' aim to uncover?

The blog post aims to uncover a legend about digital transformation and the awakening of a monolithic CMS. Source

Introducing Click to Edit

React useRef() - A complete guide

Learn how to use React's useRef Hook for DOM manipulation, performance optimization, and more in this in-depth guide.
Motunrayo Moronfolu

Written by Motunrayo 

Dec 09, 2024
React useRef() - A complete guide

The useRef Hook is a versatile tool, often overlooked but crucial for managing references, optimizing performance, and interacting directly with the Document Object Model (DOM). While it might not be as widely discussed as useState or useEffect, it plays a pivotal role in many React applications.

This guide will discuss the useRef Hook, its use cases, practical applications, and drawbacks. By the end, you'll be well equipped to leverage its full potential, unlocking new levels of efficiency and control in your React projects.

#What is useRef()?

What is useRef()?

The useRef() Hook is a built-in React feature that persists values between component re-renders. Unlike state variables managed by useState, values stored in a ref object remain unchanged across renders, making it ideal for scenarios where data doesn't directly affect the UI but is essential for the component's behavior.

#How does React useRef() work?

When React encounters a useRef() Hook, it returns a plain JavaScript object with a single property: current. This current property stores mutable values, which can be of any type, from simple values like numbers and strings to complex objects, functions, or even references to DOM elements.

How does React useRef() work?

React assigns the initial value you define to the current property of the returned reference. React will set the value of the useRef to undefined if you don't provide an initial value. Importantly, you can update this current value directly without triggering a re-render of the component. This can be seen in the snippet below:

import { useRef } from "react";
function MyComponent() {
const reference = useRef(true);
console.log(reference.current); // true
}

Also, the returned reference object is mutable. You can update the current value directly, as shown in the snippet below.

import { useRef } from "react";
function MyComponent() {
const reference = useRef(true);
const handleUpdate = () => {
reference.current = !reference.current;
};
console.log(reference.current); // true
return <button onClick={handleUpdate}>Update</button>;
}

Clicking the “Update” button changes the reference.current value from true to false and the other way around.

#Use cases of useRef() React Hook

Beyond its ability to persist values, the useRef() Hook has several vital roles in React applications:

Accessing DOM elements

Imagine a login page where users need to enter their username and password. To enhance the user experience, you can automatically direct their focus to the username field as soon as the page loads.

To achieve this, use the useRef 's capacity to access rendered DOM elements. This feature returns the referenced DOM element and its properties, providing room for direct manipulations.

import { useRef, useEffect } from “react”
function Login() {
const usernameRef = useRef(null)
useEffect(() => {
usernameRef.current.focus()
}, [])
return (
<>
<form>
<input type="text" ref={usernameRef} />
</form>
</>
)
}

The above snippet shows a Login component that renders a form with an input field for the user’s username. Also, it defines a username reference with the useRef Hook, which the focus() method is called on. This is executed inside a useEffect Hook, so it runs immediately after the UI finishes loading.

Tracking previous values

By storing the previous value of the input element as a state variable in a ref, you can monitor changes and address them accordingly. This technique is useful for implementing "undo" functionality, creating custom Hooks that need to compare previous and current values, or optimizing performance by preventing unnecessary calculations.

import { useState, useRef, useEffect } from 'react';
function Counter() {
const [count, setCount] = useState(0);
const previousCountRef = useRef(count); // Store previous count in a ref
useEffect(() => {
if (previousCountRef.current !== count) {
console.log('Count changed:', count, '(Previous:', previousCountRef.current, ')');
}
previousCountRef.current = count; // Update the ref
}, [count]); // Run the effect only when count changes
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
);
}

In this example, the useRef Hook stores the previous value of the count state variable. Every time the count changes, the useEffect Hook compares the new count to the value stored in the previousCountRef and logs a message to the console if they differ. This way, you can track how the count value evolves over time.

Managing timers and intervals

The useRef simplifies the management of timers and intervals within your components. You can store the timer's ID in a ref, allowing you to start, stop, or reset it as needed without triggering unnecessary re-renders.

import { useState, useRef, useEffect } from 'react';
function myTimer() {
const [seconds, setSeconds] = useState(0);
const timerRef = useRef(null); // Ref to store the timer ID
const startTimer = () => {
timerRef.current = setInterval(() => {
setSeconds((prevSeconds) => prevSeconds + 1);
}, 1000); // Update every second
};
const stopTimer = () => {
clearInterval(timerRef.current);
};
const resetTimer = () => {
clearInterval(timerRef.current);
setSeconds(0);
};
// Cleanup function to clear the interval when the component unmounts
useEffect(() => {
return () => clearInterval(timerRef.current);
}, []);
return (
<div>
<p>Time elapsed: {seconds} seconds</p>
<button onClick={startTimer}>Start</button>
<button onClick={stopTimer}>Stop</button>
<button onClick={resetTimer}>Reset</button>
</div>
);
}

In this example, a timer component was created using the useState and useRef Hooks. The useState Hook manages the seconds variable, which keeps track of the elapsed time. Meanwhile, useRef stores a reference to the interval ID (timerRef), which is responsible for updating the seconds every 1000 milliseconds (1 second).

The functions startTimer, stopTimer, and resetTimer control the timer's behavior. startTimer starts the interval, stopTimer stops it, and resetTimer resets the elapsed time to zero.

Building custom Hooks

When creating custom Hooks that need to maintain an internal state between renders, useRef becomes an invaluable asset. It enables you to store and update data privately within the Hook, promoting reusability and encapsulation of complex logic.

Imagine having multiple components that are required to maintain their previous state. It will appear too tedious to write this logic individually for every component. To avoid this, create a custom Hook using the useRef Hook as follows:

First, create a Hooks folder and a file usePreviousState.js, then add the following snippet:

import { useRef, useEffect } from "react";
export default function usePreviousState(value) {
const ref = useRef();
useEffect(() => {
ref.current = value;
});
return ref.current;
}

In the snippet above, a useRef instance was created, then on every page re-render, assign the value passed to the usePreviousState Hook to the ref.current. Finally, return the value of the ref.current.

To illustrate the custom Hook's utility, let’s revisit the 'tracking previous values' scenario

import { useState, usePreviousState, useEffect } from 'react';
function Counter() {
const [count, setCount] = useState(0);
const previousCount = usePreviousState(count); // Store previous count in a custom Hook
useEffect(() => {
if (previousCount !== count) {
console.log('Count changed:', count, '(Previous:', previousCount, ')');
}
previousCount = count; // Update the previous state
}, [count]); // Run the effect only when count changes
return (
<div>
<p>Count: {count}</p>
<button onClick={() => setCount(count + 1)}>Increment</button>
</div>
);
}

In the snippet above, all instances of the initial useRef were replaced with the newly created custom Hook. This shows that creating a custom Hook makes it possible to reuse complex logic.

#Optimizing performance

Beyond its DOM manipulation capabilities, useRef shines as a performance enhancer. Imagine you have a computationally intensive task within your component, such as filtering a dataset or performing calculations, re-executing these operations on every render would be wasteful.

Storing values of these calculations within a ref variable using useRef can avoid unnecessary re-computations. Since refs persist across renders without triggering updates, the calculated value remains accessible and doesn't need to be recalculated unless the underlying data changes. Let's look at the example shown below:

import { useState, useRef, useMemo } from "react";
export default function calculationComponent() {
const [inputNumber, setInputNumber] = useState(10); // Initial Calculation number
const calculateResult = useRef(null); // Ref to store the calculated result
const calculateFib = (n) => {
if (n <= 1) return n;
return calculateFib(n - 1) + calculateFib(n - 2);
};
// Memoize the calculation using useMemo
const memoizedCal = useMemo(() => {
if (
calculateResult.current &&
calculateResult.current.input === inputNumber
) {
// If the input hasn't changed, reuse the cached result
return calculateResult.current.result;
} else {
// Calculate the result and store it in the ref
const result = calculateFib(inputNumber);
calculateResult.current = { input: inputNumber, result };
return result;
}
}, [inputNumber]);
return (
<div>
<input
type="number"
value={inputNumber}
onChange={(e) => setInputNumber(parseInt(e.target.value, 10))}
/>
<p>
Result of {inputNumber} is: {memoizedCal}
</p>
</div>
);
}

In the snippet above, the useRef Hook, named calculateResult, is employed to optimize performance by caching the results of a computationally expensive calculation like the Fibonacci sequence. The calculateResult.current property stores both the input number and the calculated result, allowing for comparison on subsequent renders.

The useMemo Hook is used to memoize the calculation. It checks if the input number (inputNumber) has changed since the last render. If not, it returns the cached result from calculateResult.current, avoiding redundant computation. If the input number changes, the Fibonacci calculation is performed, and the result is stored in calculateResult.current for future reuse.

This memoization strategy improves the component's performance by preventing recalculations whenever the component re-renders due to unrelated state changes. While useRef offers performance benefits, knowing its potential drawbacks is essential.

#Drawbacks of useRef Hook

  • Manual management: Unlike state variables managed with useState or useReducer, changes to the .current property of a ref attribute do not automatically trigger re-renders of your component. This means you need to manage updates and trigger re-renders manually when necessary and can add extra complexity to your code.
  • Potential memory leaks: If you're not careful, you can create dangling refs. This happens when a ref is still holding onto a reference to a DOM element or other object that has already been unmounted or removed from the DOM, leading to memory leaks.
  • Overuse: While refs are helpful in certain scenarios, overusing them can lead to a more complex and less maintainable codebase.
  • Debugging challenges: Since changes to refs don't trigger re-renders, debugging issues related to refs can sometimes be more complicated than debugging state-related problems.
  • Not suitable for array or object updates: Although you can store arrays or objects in a ref, updating individual properties or elements within them won't trigger re-renders. You'll need to manually update the entire array or object and trigger a re-render if you want those changes to be reflected in the UI. This can require more work than using state for mutable value structures.

To mitigate these drawbacks

  • Use the useRef when necessary and prioritize managing UI-related data with state (useState or useReducer) as it automatically triggers re-renders.
  • Always ensure proper cleanup of refs when components are removed from the DOM to prevent memory leaks.
  • Leverage debugging tools like React DevTools to track ref values and their impact if your code becomes overly reliant on refs.
  • Consider alternative approaches like lifting the state up or using context to streamline state management and component communication.

#useRef vs. useState Hook

While both useRef and useState store values in React components, they serve different purposes and behave differently. Let's look at these Hooks, exploring their characteristics and how they contribute to state management in a React component.

Feature useRef useState
Mutable Yes, the .current property can be changed directly No, state updates must be done through the setter function (e.g., setCount)
Persistence a**cross r**enders Yes, the value persists for the lifetime of the component No, the value is reset on each re-render
Triggers r**e-render** No, updating the .current property does not cause a re-render Yes, updating state using the setter function triggers a re-render of the component
Common u**se c**ases Accessing DOM elements, storing previous values, managing timers/intervals, storing references Managing UI state, storing data that directly affects the component's rendering

#useRef Hook vs createRef function

Before the Hooks era, React used createRef() for refs in their application. Let's break down their key distinctions when it comes to managing refs in React applications:

Feature useRef Hook createRef Function
Component t**ype** Exclusively used in functional components (introduced in React 16.8) Designed for class components (pre-Hooks era)
Initial v**alue** Takes an optional initial value, assigned to ref.current (defaults to undefined) No initial value, ref.current is initially null
Re-renders Returns the same ref object on each re-render, maintaining its value Creates a new ref object on every re-render, losing the previous value
Persistence Value persists for the entire component lifecycle Value is lost on re-renders unless explicitly stored in a class component's instance variable
Flexibility More flexible in functional components due to its persistence Less flexible, requires additional state management for persistence in class components

If you're using functional components with React Hooks, useRef is the way to go. But if you're working with legacy class components, createRef is your best option.

However, consider refactoring to functional components and the useRef Hook for a more modern and maintainable approach. Next, let's discuss the useRef Hook in data fetched from content management systems.

useRef Hook in dynamic content fetched from CMSs

The useRef Hook, although not inherently tied to Content Management Systems (CMS), plays a crucial role in enhancing user interactions with dynamically fetched content from platforms like Hygraph, a GraphQL-Native Headless Content Management, and Federation System.

By storing references to specific elements within the fetched data, such as images or content blocks, developers can implement features like lazy loading, smooth scrolling, or interactive components.

Furthermore, useRef is valuable in optimizing data fetching from CMSs by caching results, especially for complex queries or large datasets. This caching mechanism reduces the load on the CMS and improves the application's performance as it avoids redundant data fetching operations.

#Summing it up

While often overlooked, the useRef Hook is a powerful asset in a React developer's toolkit. It excels in managing references, optimizing performance, and enabling seamless interactions with DOM elements.

Understanding its capabilities and appropriate use cases allows developers to create more efficient, maintainable, and interactive React applications. Whether you're building complex animations, managing timers, or integrating with headless CMS platforms like Hygraph to optimize content delivery, useRef proves its value repeatedly.

Ready to explore the power of Hygraph? Sign up for a free-forever developer account and experience the seamless integration of Hygraph with React and its powerful Hook like useRef.

Blog Author

Motunrayo Moronfolu

Motunrayo Moronfolu

Technical writer

Motunrayo Moronfolu is a Senior Frontend Engineer and Technical writer passionate about building and writing about great user experiences.

Share with others

Sign up for our newsletter!

Be the first to know about releases and industry news and insights.