liveBook · Manning

useTransition

As explained in React Hooks in Action: With Suspense and Concurrent Mode

useTransition is a React Hook that marks state updates as non-urgent transitions so urgent interactions can remain responsive.

useTransition marks a state change as non-urgent when the resulting UI may suspend. React can keep showing the previous interactive UI while preparing the new state, avoiding a jarring return to a loading spinner. section 1.4.1 section 13.1.1

Switching users without a receded state

A Users page displays Mark’s details while Clarisse’s data loads. Destructure the transition function and pending flag, then wrap the selection update: `const [startTransition, isPending] = useTransition();` and `startTransition(() => setSelectedUser(nextUser));`. Pass `isPending` to the details panel and apply a class such as `user-pending` to reduce opacity or otherwise signal that the displayed details are stale. If no previous UI exists, Suspense still displays its fallback. section 13.1.1 section 13.1.2

Apply the hook when an update may suspend and needs visible progress feedback:

  • Wrap only the state change that can trigger suspended children; continue showing the old UI until the new data is ready. section 13.1.1
  • Use `isPending` to indicate that the transition is underway, such as by fading stale content or displaying a delayed spinner. section 13.1.2 section 13.1.3
  • Encapsulate transition behavior in reusable design-system controls, such as a button that wraps its handler and renders pending indicators. section 13.1.3
  • Avoid leaving users in limbo: retained old content needs a clear pending signal when loading takes longer. section 13.1.1
Listing 13.2 Using a transition to improve UX on UsersPage
import {
  useState,
  unstable_useTransition as useTransition,                      #1
  Suspense
} from "react";
 
// unchanged imports
 
export default function UsersPage () {
  const [loggedInUser] = useUser();
  const [selectedUser, setSelectedUser] = useState(null);
  const user = selectedUser || loggedInUser;
  const queryClient = useQueryClient();
 
  const [startTransition] = useTransition()                     #2
 
  function switchUser (nextUser) {
    startTransition(() => setSelectedUser(nextUser));           #3
 
    queryClient.prefetchQuery(/* prefetch user details */);
    queryClient.prefetchQuery(/* prefetch user image */);
  }
 
  return user ? (
    <main className="users-page">
      <UsersList user={user} setUser={switchUser}/>
 
      <Suspense fallback={<PageSpinner/>}>                      #4
        <UserDetails userID={user.id}/>
      </Suspense>
    </main>
  ) : <PageSpinner/>;
}
#1 Import the useTransition hook.
#2 Get a transition function, startTransition.
#3 Wrap the user state change in the transition.
#4 Show a spinner while the first user loads.

Inspect the complete UsersPage pattern, including the hook import, transition-wrapped selection, prefetching, and Suspense boundary. section 13.1.1

How React Hooks in Action: With Suspense and Concurrent Mode covers it

How deep it goes
Explains returned values, transition wrapping, pending feedback, and design-system integration, but does not detail scheduler internals.
Examples
Demonstrates user selection, suspended user details, opacity feedback, pending buttons, spinners, and the UsersPage implementation.
What it assumes
Assumes React function components, Hooks, state updates, Suspense boundaries, and components that can suspend while loading data.
What you can do after
Apply useTransition to defer suspending updates, preserve interactive old UI, and communicate progress through isPending.
How it connects
Connects useTransition to Concurrent Mode, Suspense, asynchronous data loading, state updates, and reusable UI components.

Also explained in

Compare how 2 books explain useTransition →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of React Hooks in Action: With Suspense and Concurrent Mode. The section links point to the parts of the book it draws on.