What is useTransition Hook in React?

This article provides a clear guide on the useTransition hook in React, explaining its core purpose, how it works, and how to implement it to keep your application’s user interface responsive during intensive state updates.

Understanding useTransition

Introduced in React 18, useTransition is a built-in React Hook that lets you update the state without blocking the user interface. It allows you to mark certain state updates as “transitions” (non-urgent), which tells React they can be interrupted if a more urgent user interaction occurs, such as typing or clicking.

By default, all state updates in React are treated as urgent. This means if a state update causes a slow, heavy component to re-render, the entire UI can freeze and become unresponsive until the render is complete. useTransition solves this bottleneck.

Syntax

The useTransition hook does not take any arguments and returns an array with exactly two elements:

const [isPending, startTransition] = useTransition();

How to Use useTransition

Here is a practical example of how to implement useTransition. Imagine a search input that filters a massive list of items. Typing in the input should be instantaneous (urgent), but rendering the filtered list can take time (non-urgent transition).

import React, { useState, useTransition } from 'react';

function FilterList({ items }) {
  const [query, setQuery] = useState('');
  const [filteredItems, setFilteredItems] = useState(items);
  const [isPending, startTransition] = useTransition();

  const handleChange = (e) => {
    const value = e.target.value;
    
    // 1. Update the input field immediately (Urgent)
    setQuery(value);

    // 2. Defer the heavy list filtering (Non-Urgent)
    startTransition(() => {
      const filtered = items.filter(item => 
        item.toLowerCase().includes(value.toLowerCase())
      );
      setFilteredItems(filtered);
    });
  };

  return (
    <div>
      <input type="text" value={query} onChange={handleChange} />
      
      {isPending && <p>Updating list...</p>}
      
      <ul style={{ opacity: isPending ? 0.5 : 1 }}>
        {filteredItems.map((item, index) => (
          <li key={index}>{item}</li>
        ))}
      </ul>
    </div>
  );
}

In this example, if the user continues to type while the list is still filtering, React will abandon the outdated filter process and prioritize the new keystrokes. The isPending state is used to lower the opacity of the list, indicating to the user that the content is updating.

When to Use useTransition

When Not to Use It