- ReactJS Tutorial
- ReactJS - Home
- ReactJS - Introduction
- ReactJS - Installation
- ReactJS - Features
- ReactJS - Advantages & Disadvantages
- ReactJS - Architecture
- ReactJS - Creating a React Application
- ReactJS - JSX
- ReactJS - Components
- ReactJS - Nested Components
- ReactJS - Using Newly Created Components
- ReactJS - Component Collection
- ReactJS - Styling
- ReactJS - Properties (props)
- ReactJS - Creating Components using Properties
- ReactJS - props Validation
- ReactJS - Constructor
- ReactJS - Component Life Cycle
- ReactJS - Event management
- ReactJS - Creating an Event−Aware Component
- ReactJS - Introduce Events in Expense Manager APP
- ReactJS - State Management
- ReactJS - State Management API
- ReactJS - Stateless Component
- ReactJS - State Management Using React Hooks
- ReactJS - Component Life Cycle Using React Hooks
- ReactJS - Layout Component
- ReactJS - Pagination
- ReactJS - Material UI
- ReactJS - Http client programming
- ReactJS - Form Programming
- ReactJS - Controlled Component
- ReactJS - Uncontrolled Component
- ReactJS - Formik
- ReactJS - Conditional Rendering
- ReactJS - Lists
- ReactJS - Keys
- ReactJS - Routing
- ReactJS - Redux
- ReactJS - Animation
- ReactJS - Bootstrap
- ReactJS - Map
- ReactJS - Table
- ReactJS - Managing State Using Flux
- ReactJS - Testing
- ReactJS - CLI Commands
- ReactJS - Building and Deployment
- ReactJS - Example
- Hooks
- ReactJS - Introduction to Hooks
- ReactJS - Using useState
- ReactJS - Using useEffect
- ReactJS - Using useContext
- ReactJS - Using useRef
- ReactJS - Using useReducer
- ReactJS - Using useCallback
- ReactJS - Using useMemo
- ReactJS - Custom Hooks
- ReactJS Advanced
- ReactJS - Accessibility
- ReactJS - Code Splitting
- ReactJS - Context
- ReactJS - Error Boundaries
- ReactJS - Forwarding Refs
- ReactJS - Fragments
- ReactJS - Higher Order Components
- ReactJS - Integrating With Other Libraries
- ReactJS - Optimizing Performance
- ReactJS - Profiler API
- ReactJS - Portals
- ReactJS - React Without ES6 ECMAScript
- ReactJS - React Without JSX
- ReactJS - Reconciliation
- ReactJS - Refs and the DOM
- ReactJS - Render Props
- ReactJS - Static Type Checking
- ReactJS - Strict Mode
- ReactJS - Web Components
- Additional Concepts
- ReactJS - Date Picker
- ReactJS - Helmet
- ReactJS - Inline Style
- ReactJS - PropTypes
- ReactJS - BrowserRouter
- ReactJS - DOM
- ReactJS - Carousel
- ReactJS - Icons
- ReactJS - Form Components
- ReactJS - Reference API
- ReactJS Useful Resources
- ReactJS - Quick Guide
- ReactJS - Useful Resources
- ReactJS - Discussion
ReactJS - useDeferredValue Hook
The version of React 18 included a number of new React hooks that help with concurrency and rendering slow content. The useDeferredValue hook is one of those hooks that is simple to use but tough to understand. In this tutorial, we will see how this hook works so we know how and when to use it.
Working of useDeferredValue hook
In React, the useDeferredValue hook is used to interact with concurrent mode. Concurrent mode is an experimental React feature that allows us to schedule and prioritise rendering updates to create more responsive and dynamic user interfaces.
useDeferredValue is commonly used to defer the processing of certain values when they are required. This can help to minimise the amount of work done in a given render cycle and enhance our application's performance. This hook is very useful in cases when we have values that are not immediately required, such as network queries or large calculations.
We can call ‘useDeferredValue’ at the top level of our component to get a deferred version of the value.
Syntax
const deferredValue = useDeferredValue(value);
Parameter
value − It is the value we want to defer. It is typically a piece of data or a variable that can not be immediately needed or can be processed at a later time.
Return Value
The returned delayed value will be the same as the value we gave during the original render. During updates, React will first try a re-render with the old value, and then another re-render in the background with the new value.
We can use this hook in three ways. First by deferring re-rendering for a portion of the user interface, secondly by showing that the content has become old and third by showing old content while new content is loading.
Examples
So we will discuss all these three ways to use the useDeferredValue hook.
Example − Deferring re-rendering for a portion of the user interface(UI)
In a React application, we can face a situation in which a portion of our UI is slow to update and cannot make it faster. Assume that we have a text input field, and every time we write a letter, a component (such as a chart or a long list) refreshes or re-renders. This frequent re-rendering might slow down our app, even for simple operations like typing.
It's possible to use the useDeferredValue hook to avoid this slow component from affecting the rest of the UI.
import React, { useState } from 'react'; import { useDeferredValue } from 'react'; function SlowList({ text }) { // Slow operation like rendering a long list const slowListRendering = (text) => { console.log(`Rendering the list for text: ${text}`); setTimeout(() => { console.log('List rendering complete.'); }, 1000); }; slowListRendering(text); return ( <div> <p>This is a slow component.</p> {/* Render a chart here */} </div> ); } function App() { const [text, setText] = useState(''); const deferredText = useDeferredValue(text); // Defer the text input value return ( <> <input value={text} onChange={(e) => setText(e.target.value)} /> <SlowList text={deferredText} /> {/* Pass the deferred value */} </> ); } export default App;
Output
Example − Showing that the content has become old
When using useDeferredValue, it is necessary to show that the content is old in order to inform the user that the data can not be the most up-to-date due to the deferral.
In the below example, the isStale variable is calculated by comparing the deferredData to the current data. If they don't match, it means the material is out of date, and the UI shows a "Updating..." message to let the user know that the data is being updated. When using useDeferredValue, this is an easy way to deliver feedback regarding data staleness.
import React, { useState } from 'react'; import { useDeferredValue } from 'react'; function MyComponent({ deferredData }) { // Slow operation function slowOperation(data) { return new Promise((resolve) => { setTimeout(() => { resolve(`Processed data: ${data}`); }, 2000); }); } const [data, setData] = useState('Initial data'); // Initialize data const isStale = deferredData !== data; if (isStale) { // Data is old, simulate loading slowOperation(deferredData).then((result) => { setData(result); // Update data when it's no longer old }); } return ( <div> <p>Data: {data}</p> {isStale && <p>Updating...</p>} </div> ); } function App() { const [inputData, setInputData] = useState(''); const deferredInputData = useDeferredValue(inputData); return ( <div> <input type="text" value={inputData} onChange={(e) => setInputData(e.target.value)} /> <MyComponent deferredData={deferredInputData} /> </div> ); } export default App;
Output
Example − Showing old content while new content loads
We can use useDeferredValue to preserve both the old and new data states and conditional render them based on the staleness of the data to show old content while new content loads. Here's an example to demonstrate −
data.js
let cache = new Map(); export function fetchData(url) { if (!cache.has(url)) { cache.set(url, getData(url)); } return cache.get(url); } async function getData(url) { if (url.startsWith("/search?q=")) { return await getSearchResults(url.slice("/search?q=".length)); } else { throw Error("Not Found"); } } async function getSearchResults(query) { // Delay to make waiting await new Promise((resolve) => { setTimeout(resolve, 400); }); const allData = [ { id: 1, title: "ABC", year: 2000 }, { id: 2, title: "DEF", year: 2001 }, { id: 3, title: "GHI", year: 2002 }, { id: 4, title: "JKL", year: 2003 }, { id: 5, title: "MNO", year: 2004 }, { id: 6, title: "PQR", year: 2005 }, { id: 7, title: "STU", year: 2006 }, { id: 8, title: "VWX", year: 2007 }, { id: 9, title: "YZ", year: 2008 } ]; const lowerQuery = query.trim().toLowerCase(); return allData.filter((data) => { const lowerTitle = data.title.toLowerCase(); return ( lowerTitle.startsWith(lowerQuery) || lowerTitle.indexOf(" " + lowerQuery) !== -1 ); }); }
SearchData.js
import { fetchData } from "./data.js"; export default function SearchData({ query }) { if (query === "") { return null; } const myData = use(fetchData(`/search?q=${query}`)); if (myData.length === 0) { return ( <p> No data found for <i>"{query}"</i> </p> ); } return ( <ul> {myData.map((data) => ( <li key={data.id}> {data.title} ({data.year}) </li> ))} </ul> ); } function use(promise) { if (promise.status === "fulfilled") { return promise.value; } else if (promise.status === "rejected") { throw promise.reason; } else if (promise.status === "pending") { throw promise; } else { promise.status = "pending"; promise.then( (result) => { promise.status = "fulfilled"; promise.value = result; }, (reason) => { promise.status = "rejected"; promise.reason = reason; } ); throw promise; } }
App.js
import { Suspense, useState } from 'react'; import SearchData from './SearchData.js'; export default function App() { const [query, setQuery] = useState(''); return ( <> <label> Search for the Data here: <input value={query} onChange={e => setQuery(e.target.value)} /> </label> <Suspense fallback={<h2>Data is Loading...</h2>}> <SearchData query={query} /> </Suspense> </> ); }
Output
Limitations
In React, the useDeferredValue hook has a few limitation that can be defined in a few words −
Some older web browsers may not completely support the useDeferredValue hook. As a result, if we need to support outdated browsers, we may have difficulties.
Using useDeferredValue might complicate our code, when dealing with multiple deferred values. This additional complexity can make our code more difficult to understand and maintain.
While useDeferredValue can help with performance, it's not the best solution for all performance issues. We still need to consider other performance optimizations like code splitting and server-side rendering for better results.
If the developer is new to React, it may require effort and some time to understand the useDeferredValue hook.
To Continue Learning Please Login
Login with Google