Concurrent React ⚛️⏱️
React 18+ introduces concurrency primitives that keep UIs responsive by letting React prioritize urgent work and pause non-critical updates.
1) startTransition / useTransition 🔄
startTransition (outside components)
import { startTransition } from "react";
function Search({ query }) {
function handleInput(event) {
const value = event.target.value;
setImmediateQuery(value); // urgent update
startTransition(() => {
setDeferredQuery(value); // non-urgent, can be interrupted
});
}
}- Urgent updates (text input) happen immediately.
- Non-urgent updates (filtering, navigation) can be interrupted if new input arrives.
useTransition (inside components)
const [isPending, startTransition] = useTransition();
startTransition(() => {
setSearchResults(expensiveLookup(value));
});isPendingtoggles fallback UI (spinners) while low-priority work finishes.
2) Suspense Boundaries 🧱
Suspense coordinates asynchronous UI.
<Suspense fallback={<Skeleton />}>
<Comments />
</Suspense>- Boundary shows fallback while children load data (with Suspense-enabled fetchers) or lazy components.
- Use multiple boundaries to isolate slow sections.
3) Streaming SSR Concepts 🌐
- Frameworks like Next.js and Remix leverage
renderToPipeableStreamto stream HTML progressively. - Suspense boundaries allow sending shell content immediately while deferring slower chunks.
- Benefits: faster Time to First Byte (TTFB), earlier interactivity.
🧠 Even if you use a framework, understanding streaming helps diagnose hydration issues.
4) Avoiding UI Jank 🧘
- Separate urgent updates (typing, pointer movement) from non-urgent ones (filters, analytics) via transitions.
- Defer expensive operations using
useDeferredValuefor derived data.
const deferredQuery = useDeferredValue(query);
const filteredItems = useMemo(() => filter(items, deferredQuery), [items, deferredQuery]);- Keep Suspense fallbacks friendly (skeletons, shimmer) to mask latency.
Key Takeaways ✅
- React’s concurrency primitives let you prioritize user input over heavy computations.
- Suspense boundaries delineate loading regions both on client and server (streaming SSR).
- Distinguish urgent vs non-urgent updates to prevent jank.
- Frameworks bake in streaming, but developers must place Suspense and transitions intentionally.
Recap 🔄
Concurrent React empowers apps to remain responsive: use startTransition/useTransition for low-priority work, place Suspense boundaries around asynchronous sections, embrace streaming SSR for quicker payloads, and plan UX fallbacks so urgent interactions never stall.
Last updated on