useDeferredValue lets you defer updating a part of the UI
const deferredValue = useDeferredValue(value)
useDeferredValue is react hook. You can call this hook at the top of your component to get a deferred version of the value.
import { useState, useDeferredValue } from 'react';
function SearchPage() {
const [query, setQuery] = useState('');
const deferredQuery = useDeferredValue(query);
// ...
}
Parameters
- value: the value you want to defer. It can have any type
Returns
During the inital render the first value rendered will be the one that you provided.
During updates react will render the old value provided and then try to re render the new value in the as it becomes available.
Caveats
- useDeferredValue accepts primitive values like Strings and numbers or Objects that are created outside of rendering
- If you create new Object during the rendering and pass it to useDeferredValue, it may be different on every re render
- useDeferred value is integrated with suspense. the user will see the old deferred value untill the data loads. User will not see the fallback value if a new background update suspends the UI
- Any updates caused by events like typing are prioritized over the background-re render. There is no fixed delay caused by
useDeferredValue
As soon as react finishes the old render, it will start working on the beackground re render with new deferred value - useDeferredValue does not itself prevent extra network requests
- The backgroud re render caused by useDeferredValue does not fire Effects untill it is committed to the screen
- If the background re render suspends its effects will fire after the UI updates
How to use useDeferred value
The main utility of useDeferred value is to show stale content while the new content is loading
Here is how you can use useDeferredValue
call the hook on top of your component
import { useState, useDeferredValue } from 'react';
function SearchPage() {
const [query, setQuery] = useState('');
const deferredQuery = useDeferredValue(query);
// ...
}
we have already explained how the useDeferred value works but I will do it again
When the initial render occurs the deferred value is the value that you provided but
in subsequent renders the deferred value will be the old value and then react will try to re render the new value in the background.
example:
Note before starting the example
- In this example we assume that the app uses one of the Suspense-enabled data sources
- Lazy-loading the components we lazy
In this example we have a component named SearchResults
which suspends when getting search results from the database
If you are looking for a React Native Chat SDK to build in app chat messaging application, you can consider DeadSimpleChat React Native SDK
import { Suspense, useState } from 'react';
import SearchResults from './SearchResults.js';
export default function App() {
const [query, setQuery] = useState('');
return (
<>
<label>
Search albums:
<input value={query} onChange={e => setQuery(e.target.value)} />
</label>
<Suspense fallback={<h2>fetching...</h2>}>
<SearchResults query={query} />
</Suspense>
</>
);
}
A common pattern is to keep showing the older results until new results are available to show
We can call useDeferredValue
to pass a deferred version of the query down
export default function App() {
const [query, setQuery] = useState('');
const deferredQuery = useDeferredValue(query);
return (
<>
<label>
Search all albums:
<input value={query} onChange={e => setQuery(e.target.value)} />
</label>
<Suspense fallback={<h2>fetching...</h2>}>
<SearchResults query={deferredQuery} />
</Suspense>
</>
);
}
the query will update immediately so the input will display the new value.
deferredQuery will keep its previous value until the data has loaded, So SearchResults
will show the stale results for a bit
Enter "a" in the example and wait for the results to load and then edit the input to "ab"
Instead of the Suspense fallback we will see the old result until the new results are loaded
import { Suspense, useState, useDeferredValue } from 'react';
import SearchResults from './SearchResults.js';
export default function App() {
const [query, setQuery] = useState('');
const deferredQuery = useDeferredValue(query);
return (
<>
<label>
Search albums:
<input value={query} onChange={e => setQuery(e.target.value)} />
</label>
<Suspense fallback={<h2>Loading...</h2>}>
<SearchResults query={deferredQuery} />
</Suspense>
</>
);
}
Indicating that the content is stale
there is no indication that the result list for the latest query is still loading. This could be confusing to the user if the results take some time to load. We can add a visual indication when the old result is still displayed.
Conclusion
In this article we have explained how to use useDeferredValue with examples
Thanks for reading the article