Skip to content
ReactField

Topics

React Rendering Strategies

Choose React rendering strategies for each route: CSR, SSR, SSG, ISR, and Server Components, with practical defaults.

Mohamed ElshahawyPublished Apr 2026Updated Oct 2026
5 min read

Explore React rendering from the server-rendered and jQuery era to SPAs, SSR, SSG, and RSC, with real-world examples and diagrams that help you choose the right approach for your app.

Section 1: The Evolution of React Rendering

React rendering patterns did not appear all at once. They evolved as teams hit real production problems:

  • Server-rendered pages gave simplicity and SEO, but full-page reloads and limited interactivity.
  • jQuery improved interactions, but scaling app-level state became hard.
  • Early SPA frameworks proved browser-driven apps were viable.
  • React (2013) won by introducing a clearer state-driven rendering model and predictable UI updates.

The key lesson is not "one strategy wins forever." Each pattern exists because it solves a specific constraint (SEO, TTI, interactivity, infrastructure cost, or DX).

Evolution of React rendering

  1. 2024Server ComponentsHybrid rendering with streaming
  2. 2020Static generationGatsby and Next.js SSG
  3. 2016Server-side renderingNext.js SSR
  4. 2013React SPAClient-side rendering
  5. 2005jQueryDirect DOM manipulation

Why this matters in ReactField

When you choose rendering strategy first (instead of trend-first), architectural decisions become easier:

  • Authenticated dashboard with long sessions -> SPA can be excellent.
  • Content-heavy public pages with SEO constraints -> SSR/SSG often better.
  • Mixed app/site products -> hybrid approach is usually the practical answer.

Section 2: Client-Side Rendering (SPA)

A server sends an almost empty page and an orange JavaScript bundle to the browser, where a person with a paint roller builds the page
With CSR the server sends a shell and JavaScript. The page is built inside the browser.

In a traditional SPA, the server usually returns an HTML shell and JavaScript bundle. The browser then executes the app and React renders the UI client-side.

TSX
// main.tsx: React takes ownership of rendering
import { createRoot } from 'react-dom/client'
import { BrowserRouter } from 'react-router-dom'
import { App } from './App'

const root = createRoot(document.getElementById('root')!)
root.render(
  <BrowserRouter>
    <App />
  </BrowserRouter>
)

SPA loading sequence (mental model)

  1. Browser requests HTML shell
  2. Browser downloads JS bundle
  3. Browser parses and executes JS
  4. React mounts and renders initial UI
  5. Client-side data fetching starts
  6. UI updates with fetched data

This sequence explains common SPA bottlenecks:

  • Bundle size delays first contentful render
  • Fetch-on-render can create data waterfalls
  • All-JS dependency can fail hard if script loading fails, including when a deployment removes chunks an open tab still needs (The Hidden Side of Frontend Deployments)

Example: classic fetch-after-mount pattern

TSX
function Dashboard() {
  const [stats, setStats] = useState<any>(null)
  const [loading, setLoading] = useState(true)

  useEffect(() => {
    fetch('/api/dashboard-stats')
      .then((res) => res.json())
      .then((data) => {
        setStats(data)
        setLoading(false)
      })
  }, [])

  if (loading) return <DashboardSkeleton />
  return <DashboardGrid stats={stats} />
}

This works, but remember: the request starts only after bundle download, parse/execute, and component mount.

Section 3: Server-Side Rendering (SSR)

A browser requests a page, the server assembles the full page with a gear, and the finished page arrives in the browser
With SSR the server builds the full HTML for each request, so the browser shows content right away.

SSR renders HTML on the server for each request, then sends ready-to-display markup to the browser.

When SSR helps

  • Public pages where SEO and link previews matter.
  • Content that must appear quickly on first load.
  • Routes where server-side auth checks are required before page content.

Trade-offs

  • More server work per request.
  • Caching strategy is critical to control infra cost.
  • You still ship client JS for interactivity, so SSR is not "no JavaScript."
TSX
// app/blog/[slug]/page.tsx (Next.js App Router)
export default async function BlogPostPage({
  params,
}: {
  params: { slug: string }
}) {
  const post = await getPostBySlug(params.slug)

  return (
    <article>
      <h1>{post.title}</h1>
      <p>{post.body}</p>
    </article>
  )
}

Section 4: Static Site Generation (SSG)

A printing press labelled Build produces stacks of pages ahead of time, which sit on CDN shelves and are handed instantly to many browsers
With SSG pages are printed once at build time and served from the CDN to every visitor.

SSG pre-renders pages at build time and serves them from CDN edge nodes.

When SSG helps

  • Docs, marketing pages, blogs, changelogs.
  • Content that does not need per-request personalization.
  • Teams that want the best cacheability and very low TTFB.

Trade-offs

  • Content freshness depends on rebuild/revalidation strategy.
  • Very large sites can have longer build times.

The revalidate: 60 below is Incremental Static Regeneration. Update Content Without Redeploying explains how it works, how on-demand revalidation differs, and which caches can still serve old pages.

TSX
// pages/docs/[slug].tsx (Pages Router style)
export async function getStaticProps({ params }: { params: { slug: string } }) {
  const doc = await getDoc(params.slug)
  return { props: { doc }, revalidate: 60 }
}

Section 5: React Server Components (RSC)

A page made of grey blocks rendered on the server and two orange interactive blocks handled on the client
With RSC most of the page renders on the server. Only the interactive parts ship JavaScript to the client.

RSC lets some components run only on the server, reducing client bundle size and avoiding unnecessary hydration work.

Why teams adopt RSC

  • Less JavaScript sent to the browser.
  • Direct server-side data access for server components.
  • Better default path for mixing static, dynamic, and interactive islands.

Practical boundary pattern

TSX
// Server component
import ClientChart from './ClientChart'

export default async function AnalyticsPanel() {
  const summary = await getAnalyticsSummary()
  return (
    <section>
      <h2>Analytics</h2>
      <p>Total users: {summary.totalUsers}</p>
      <ClientChart data={summary.chartData} />
    </section>
  )
}
TSX
// Client component
'use client'

export default function ClientChart({ data }: { data: number[] }) {
  return <ChartLibrary data={data} />
}

Section 6: Patterns in the Real World

Most production apps are hybrid, not pure CSR/SSR/SSG.

Route TypeTypical StrategyWhy
Marketing landingSSG + occasional revalidationfast global delivery, strong SEO
Blog/article pagesSSG or SSRcrawlable content, share previews
Logged-in dashboard shellCSR or RSC-hybridrich interactions after login
Account/settingsSSR or RSC-hybridauth checks + dynamic server data
Admin data gridsCSR with route-level loadersresponsiveness for heavy interactions

A useful default: SSG for public static content, SSR/RSC for dynamic server data, CSR islands for rich interactivity.

Practical Takeaways

  • SPAs shine for highly interactive, authenticated, long-session applications.
  • Initial-load performance depends heavily on code splitting and data-loading strategy.
  • Use profiler and network waterfall analysis before selecting optimization tactics.
  • Modern React apps usually combine strategies route-by-route.
  • Pick rendering based on user needs and constraints, not trend cycles.

Decision framework

Need a short picker? Use When to use SSR, SSG, ISR, or CSR. For component boundaries, see Server vs Client Components.

ConstraintLean toward
Public SEO + rare editsSSG
Public SEO + frequent editsISR or SSR
Per-request private HTMLSSR
Auth app shellCSR or hybrid
Interactive leaf onlyClient Component island

When not to change strategy

  • You have not identified SEO, freshness, or personalization as the constraint
  • You are mid-migration without measuring TTFB or LCP

Checklist

  • Strategy chosen per route, not one global slogan
  • Public pages have meaningful first HTML
  • Client JS limited to interactive islands where possible

Source