Skip to content
GeeksSmith
advanced 7 min read

Concurrent React, Transitions & Suspense

Concurrent React is an interruptible rendering engine that prioritizes urgent user inputs (typing, clicking) over non-urgent background transitions (filtering, data fetching) without blocking the main thread.

Why it matters in interviews

Concurrent rendering eliminates input lag (INP) on heavy screens by allowing React to pause in-flight renders, handle clicks immediately, and stream UI asynchronously via Suspense boundaries.

Visual & Interactive Explanation

Synchronous vs Concurrent Rendering Comparison

Interactive Comparison

Legacy Synchronous

Blocking Call Stack

Blocking (INP Lag)
RenderingUninterruptible run-to-completion
User InputBlocked until render completes
Fallback UIManual isLoading boolean state
Strengths
  • Simple mental model
Trade-offs
  • High INP / Frame drops
  • Janky typing experience

Concurrent React 18+

Time-Sliced Fiber Work Loop

Responsive at 60fps
RenderingInterruptible time-sliced yielding
User InputInstant priority preemption
Fallback UIDeclarative <Suspense> boundaries
Strengths
  • Zero input lag (low INP)
  • Streaming SSR + Selective Hydration
Trade-offs
  • Renders may run multiple times if interrupted

Code Examples & Implementation

useTransition to Prevent Input Freeze on Heavy Filter
import { useState, useTransition } from 'react';

export function FastSearch() {
  const [inputVal, setInputVal] = useState('');
  const [query, setQuery] = useState('');
  const [isPending, startTransition] = useTransition();

  const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    // 1. Urgent update: update input immediately (0ms delay)
    setInputVal(e.target.value);

    // 2. Non-urgent transition: heavy filter runs in background
    startTransition(() => {
      setQuery(e.target.value);
    });
  };

  return (
    <div>
      <input value={inputVal} onChange={handleChange} placeholder="Search 5,000 items..." />
      {isPending && <span className="text-signal-amber text-xs">Filtering...</span>}
      <HeavyList query={query} />
    </div>
  );
}

Interview-Ready Answers

Concurrent React makes rendering interruptible. `startTransition` marks updates as low priority so user typing remains instant while a heavy list renders in the background. Suspense shows fallback UI while async data or code loads.

Official Documentation & Specifications

Follow-up Questions & Deep Dives

🎯 Code Output — What Does This Print?

Question 1hard
function App() {
  const [text, setText] = useState("");
  const [items, setItems] = useState<string[]>([]);
  const [isPending, startTransition] = useTransition();

  const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
    setText(e.target.value);
    startTransition(() => {
      const filtered = hugeList.filter((item) => item.includes(e.target.value));
      setItems(filtered);
    });
  };

  console.log("render, isPending:", isPending);
  return <input value={text} onChange={handleChange} />;
}
// User types "a". How many renders and what isPending values?
Question 2medium
function App() {
  return (
    <Suspense fallback={<p>Loading...</p>}>
      <LazyComponent />
    </Suspense>
  );
}

const LazyComponent = React.lazy(() => import("./Heavy"));
// What does the user see initially?

Common Mistakes & Anti-Patterns

  • Putting urgent input updates inside startTransition (causes laggy typing feeling)
  • Assuming code inside startTransition runs asynchronously like setTimeout (it runs synchronously during work loop setup)
  • Having side-effects in render functions (which can run multiple times when interrupted in concurrent mode)

Real-World Architectural Scenario

A user types in a live filter input. With 10,000 items, each keystroke lags by 300ms. Debouncing helps API calls, but local UI typing is still laggy. How do you fix it?

Rate Your Readiness

Rate how comfortably you can explain this in an interview to update your global readiness gauge:

Rate your confidence: