← Back to blog

useTransition

useTransition marks state updates as non-urgent, keeping your UI responsive during expensive operations.

Example: DeletePostButton

From app/dashboard/[slug]/_components/DeletePostButton.tsx:

'use client'; import { useTransition } from 'react'; export function DeletePostButton({ slug }) { const router = useRouter(); const [isPending, startTransition] = useTransition(); function deleteAction() { startTransition(async () => { await deletePost(slug); router.push('/dashboard'); }); } return ( <button onClick={deleteAction} disabled={isPending}> {isPending ? 'Deleting...' : 'Delete'} </button> ); }

When clicked, isPending becomes true immediately and stays true until the Server Function and navigation complete.

Caveat: State Updates After Await

State updates after await need nested startTransition:

startTransition(async () => { await someAsyncFunction(); startTransition(() => { setState('done'); }); // ✅ });

In the delete example, router.push handles this internally.

March 5, 2026123 words