useTransition
All about useTransition in React
Improve performance by non-blocking the UI.
Good to know:
Use only when wrappring a setter
function of an state.
import { useTransition } from 'react';
function TabContainer() {
const [isPending, startTransition] = useTransition();
...
}
Everything inside the startTransition
callback is marked as a low priority/Transitions
. All Transitions
can be interrupted in the middle of a re-render by other state updates/state setters (higher priority). Once all higher priority done, Transitions
work are continue (restarts its rerender).
- Setting 1000 items while the user interacts with a filter component. The user will be able to interact with the filter component since setting items are marked as
Transition
. - Changing tabs that renders a component with millions items while user clicks other tabs or components. By wrapping the
setter
of tabs withstartTransition
, the UI won't block.
export default function TabContainer() {
const [tab, setTab] = useState('about');
const [isPending, startTransition] = useTransition();
// ⬇️
function selectTab(nextTab) {
startTransition(() => {
setTab(nextTab);
});
}
return
<>
<TabButton onClick={() => selectTab('about')} >
About
</TabButton>
<TabButton onClick={() => selectTab('posts')} >
Posts (slow)
</TabButton>
{tab === 'about' && <AboutTab />}
{tab === 'posts' && <PostsTab />}
</>
}
In React 19, it will be available for async operations.
function onSubmit(data: Inputs) {
if (!isLoaded) return
startTransition(async () => {
try {
const result = await signIn.create({
identifier: data.email,
password: data.password,
})
if (result.status === "complete") {
await setActive({ session: result.createdSessionId })
router.push(`${window.location.origin}/`)
} else {
/*Investigate why the login hasn't completed */
console.log(result)
}
} catch (error) {
const unknownError = "Something went wrong, please try again."
isClerkAPIResponseError(error)
? toast.error(error.errors[0]?.longMessage ?? unknownError)
: toast.error(unknownError)
}
})
}