PresentationInteractive, narrated presentation of the section content.
ContentDetailed description of the section content.
Lesson: Deep Dive into <strong>useTransition</strong> Hook in React
1. Introduction: Why Do We Need <strong>useTransition</strong>?
Imagine you’re building a search feature for a large dataset. As the user types, the UI updates with search results. However, if rendering the results is slow, the UI may feel laggy. How can we ensure a smooth, responsive experience?
This is where React’s useTransition hook helps. It allows us to prioritize urgent updates (like typing) while deferring expensive updates (like rendering a long list). This keeps the app feeling snappy and interactive.
Real-world Scenario
Let’s say you have an app where users filter a list of products as they type. Without useTransition, every keystroke immediately triggers a re-render, which can slow down typing. Using useTransition, we can ensure that:
- Typing remains fast (high-priority updates).
- Filtering updates the list asynchronously (low-priority updates).
2. Understanding <strong>useTransition</strong>
How Does <strong>useTransition</strong> Work?
useTransition lets us mark updates as non-blocking, meaning React won’t prioritize them over urgent interactions (like typing or clicking).
It returns two values:
jsx
CopyEdit
const [isPending, startTransition] = useTransition();
<strong>isPending</strong>: Boolean that tells us if a transition is ongoing. Useful for showing a loading state.<strong>startTransition</strong>: A function that wraps low-priority updates.
3. Example: Slow Filtering Without <strong>useTransition</strong>
Problem: UI Freezes When Typing
Without useTransition, every keystroke triggers a blocking update, making typing slow when filtering a large dataset.
import React, { useState } from "react";
const products = Array.from({ length: 10000 }, (_, i) => `Product ${i + 1}`);
function ProductList() {
const [query, setQuery] = useState("");
const [filteredProducts, setFilteredProducts] = useState(products);
const handleSearch = (e) => {
setQuery(e.target.value);
// Expensive operation: filtering 10,000 items every keystroke
setFilteredProducts(products.filter((p) => p.includes(e.target.value)));
};
return (
<div>
<input type="text" value={query} onChange={handleSearch} placeholder="Search..." />
<ul>
{filteredProducts.map((product) => (
<li key={product}>{product}</li>
))}
</ul>
</div>
);
}
export default ProductList;
Issue
- As users type, React blocks the UI to update
filteredProducts. - The input lags when typing quickly.
4. Solution: Using <strong>useTransition</strong> for a Smoother UI
Key Fix: Wrap Filtering in <strong>startTransition</strong>
import React, { useState, useTransition } from "react";
const products = Array.from({ length: 10000 }, (_, i) => `Product ${i + 1}`);
function ProductList() {
const [query, setQuery] = useState("");
const [filteredProducts, setFilteredProducts] = useState(products);
const [isPending, startTransition] = useTransition();
const handleSearch = (e) => {
setQuery(e.target.value);
// Move expensive filtering inside startTransition
startTransition(() => {
setFilteredProducts(products.filter((p) => p.includes(e.target.value)));
});
};
return (
<div>
<input type="text" value={query} onChange={handleSearch} placeholder="Search..." />
{isPending && <p>Loading...</p>} {/* Show a loading state */}
<ul>
{filteredProducts.map((product) => (
<li key={product}>{product}</li>
))}
</ul>
</div>
);
}
export default ProductList;
Why This Works?
- Typing remains instant: The UI updates query immediately.
- Filtering is deferred: React processes it in the background.
- The UI never freezes, even with 10,000+ items.
- A loading indicator (
<strong>isPending</strong>) improves UX.
5. When to Use <strong>useTransition</strong>?
✅ Use useTransition when:
- You have expensive computations (e.g., filtering, sorting, data-heavy UI updates).
- You want to prioritize user interactions (like typing, clicking).
❌ Avoid useTransition if:
- Updates must be immediate (e.g., form validation, real-time UI changes).
- The expensive update is already optimized via memoization or virtualization.
6. Summary
useTransitionprioritizes urgent updates while deferring expensive ones.- It keeps the UI responsive and smooth.
- Example: Filtering a large list while typing remains instant.
- Use it only when needed, especially for CPU-heavy UI updates.
No hints available.