React Easy technical 0 views 2 min read

What is Streaming SSR and how does React 18+ improve it?

Peer-reviewed by HireXTech Technical Panel Updated for 2025/2026 hiring Editorial standards
Practise this track
Interviewer Expectations for this Question
01
Core Competency

Assesses fundamental understanding of React conventions, runtime behavior, and memory/performance considerations.

02
Evaluation Criteria

Hiring managers look for precision, avoidance of ambiguous jargon, and ability to explain trade-offs under real production conditions.

Comprehensive Model Answer Verified Solution

Streaming SSR sends HTML to the browser in chunks as it's generated, rather than waiting for the entire page. React 18+ dramatically improves this with Suspense integration.

#### Traditional SSR (Pre-React 18)

     Server: Wait for ALL data → Generate ALL HTML → Send to client
     Client: Receive HTML → Download ALL JS → Hydrate ALL components
     Problem: Slow components block entire page!
     

#### Streaming SSR (React 18+)

     Server: Send HTML as it's ready, wrap slow parts in <Suspense>
     Client: Render immediately, hydrate progressively
     Benefit: User sees content faster!
     

#### Basic Example

     import { Suspense } from 'react';

     export default function Page() {
       return (
         <html>
           <body>
             {/* Sent immediately */}
             <header>
               <h1>My App</h1>
             </header>

             {/* Sent immediately with fallback */}
             <Suspense fallback={<div>Loading comments...</div>}>
               <Comments /> {/* Streamed when ready */}
             </Suspense>

             {/* Also streamed separately */}
             <Suspense fallback={<div>Loading recommendations...</div>}>
               <Recommendations /> {/* Streamed when ready */}
             </Suspense>

             <footer>© 2026</footer>
           </body>
         </html>
       );
     }
     

#### Server Component with Data Fetching

     // This is a Server Component (async!)
     async function Comments() {
       const comments = await db.comments.findMany();
       
       return (
         <ul>
           {comments.map(comment => (
             <li key={comment.id}>{comment.text}</li>
           ))}
         </ul>
       );
     }
     

#### How It Works

  1. Server starts sending HTML immediately
  2. When it hits <Suspense>, it sends the fallback
  3. Continues streaming rest of the page
  4. When data is ready, sends the actual component
  5. Client replaces fallback with real content
  6. Hydration happens independently per component

#### Selective Hydration

     function App() {
       return (
         <div>
           <header>Header</header> {/* Hydrates first */}
           
           <Suspense fallback={<Spinner />}>
             <HeavyComponent /> {/* Hydrates when user interacts */}
           </Suspense>
           
           <Suspense fallback={<Spinner />}>
             <Comments /> {/* Hydrates independently */}
           </Suspense>
         </div>
       );
     }
     

#### Benefits

  • Faster TTFB (Time to First Byte): User sees content sooner
  • Better UX: Progressive loading instead of blank screen
  • Prioritized hydration: Interactive elements hydrate first
  • Resilient: Slow components don't block fast ones

#### Next.js App Router Example

     // app/page.tsx
     import { Suspense } from 'react';
     import ProductList from './ProductList';
     import Reviews from './Reviews';

     export default function ProductPage() {
       return (
         <div>
           <h1>Product Page</h1>
           
           {/* Streams product list first */}
           <Suspense fallback={<ProductSkeleton />}>
             <ProductList />
           </Suspense>

           {/* Reviews stream separately */}
           <Suspense fallback={<ReviewSkeleton />}>
             <Reviews />
           </Suspense>
         </div>
       );
     }

     // These are async Server Components
     async function ProductList() {
       const products = await fetchProducts(); // Doesn't block Reviews
       return <div>{/* render products */}</div>;
     }

     async function Reviews() {
       const reviews = await fetchReviews(); // Doesn't block ProductList
       return <div>{/* render reviews */}</div>;
     }
     

#### Key Requirements

  • Use React 18+ with createRoot and hydrateRoot
  • Wrap slow components in <Suspense>
  • Use frameworks supporting streaming (Next.js, Remix, etc.)
  • Server must support streaming responses

Candidate Response Strategy & Interview Tips

  1. Start with a concise one-sentence summary: Deliver a direct, confident answer first before expanding into nuances.
  2. Demonstrate real-world trade-offs: Discuss where this approach excels and when you would avoid it in production systems.
  3. Discuss complexity & edge cases: Proactively explain time/space complexity or boundary conditions (null values, scale limits).
  4. Prepare for interviewer follow-ups: Technical hiring panels frequently probe deeper into concurrency, backward compatibility, or alternative libraries.
Related Topics & Skills
Spotted an error or have an alternative solution?