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

