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

  • useTransition prioritizes 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.

Discuss with OthersAsk questions, share your thoughts, and discuss with other learners.

Loading discussion ...
Setup
React Fundamentals
Next.js
Advanced React
Databases
React Hooks
Authentication and Authorisation
APIs
CI/CD and DevOps
Testing React
Advanced Topics