React useTransition — Keeping UI Responsive During Heavy Updates

Learn how to use useTransition to keep your UI responsive during expensive state updates. Covers tab switching, filtering, navigation transitions, and the isPending flag.

Transition Hooks

Detailed Explanation

Responsive UI with useTransition

useTransition marks state updates as non-urgent transitions, allowing React to interrupt them to keep the UI responsive for higher-priority updates like typing.

The Problem

When switching tabs or filtering large lists, a heavy render can freeze the entire UI:

// Without useTransition -- UI freezes while rendering 10000 items
function handleTabChange(tab: string) {
  setTab(tab); // Blocks the UI until the render completes
}

The Solution

const [isPending, startTransition] = useTransition();

function handleTabChange(tab: string) {
  startTransition(() => {
    setTab(tab); // Non-urgent -- React can interrupt this
  });
}

return (
  <>
    {isPending && <Spinner />}
    <TabContent tab={tab} />
  </>
);

How It Works

  1. React starts rendering the transition update
  2. If a higher-priority update arrives (e.g., user types in an input), React pauses the transition
  3. React renders the urgent update immediately
  4. React resumes the transition when the main thread is free
  5. isPending is true while the transition render is in progress

Tab Switching Pattern

function TabContainer() {
  const [tab, setTab] = useState("home");
  const [isPending, startTransition] = useTransition();

  function selectTab(nextTab: string) {
    startTransition(() => setTab(nextTab));
  }

  return (
    <div>
      <nav style={{ opacity: isPending ? 0.7 : 1 }}>
        {["home", "posts", "settings"].map(t => (
          <button key={t} onClick={() => selectTab(t)}>
            {t}
          </button>
        ))}
      </nav>
      <TabContent tab={tab} />
    </div>
  );
}

Key Constraints

  • The callback passed to startTransition must be synchronous
  • It only wraps state updates -- not async operations directly
  • Keep input state that controls typing outside the transition

Use Case

Use useTransition for tab switching with expensive child rendering, navigation transitions, filtering large lists without blocking input, and any UI update that can tolerate being interrupted.

Try It — React Hooks Reference

Open full tool