C.W.K.
Stream
Lesson 01 of 08 · published

React Is a Library, Not a Framework

~22 min · React, Next.js, framework, DIY tax

Level 0Curious
0 XP0/68 lessons0/11 achievements
0/120 XP to next level120 XP to go0% complete

The gap React leaves on the floor

React ships a component model and a renderer. It does not ship routing, server rendering, data fetching conventions, code splitting, build tooling, or deployment. Every React-only app reinvents those pieces from npm packages and glue code, and then maintains the glue forever.

What you end up wiring by hand

  • Routing — React Router or TanStack Router, plus a strategy for nested layouts.
  • Server rendering — SSR setup, hydration boundaries, streaming.
  • Data fetching — where, when, how to cache.
  • Code splitting — dynamic imports, prefetch, chunking.
  • Build tooling — Vite/Webpack/Turbopack config, env loading, source maps.
  • Deployment — static vs Node server vs edge runtime.

Why a framework wins for app work

The React team itself now recommends starting with a framework. Standalone Create React App was retired specifically because the gap above kept biting beginners. Next.js fills the gap with conventions: file-system routing, Server Components by default, fetch-with-caching primitives, image/font/script optimizers, and a production server that runs anywhere Node runs.

Where this lesson lands

You'll build everything from this point on under those conventions. When something feels surprising later (params is a Promise, fetch isn't cached, components render on the server), remember the trade: you stop owning the wiring; in exchange you accept the framework's opinions.

Code

Pure React leaves the gap visible·tsx
import { useState } from 'react';

// React gives you components and re-renders. Nothing else.
export function App() {
  const [count, setCount] = useState(0);
  return <button onClick={() => setCount(c => c + 1)}>{count}</button>;
}

// No answer for:
//   - How does this HTML reach the browser before JS hydrates?
//   - How does /about navigate?
//   - How do you fetch on the server?
//   - How do you bundle?
//   - How do you deploy?
Same component inside a Next.js app·tsx
// app/page.tsx — Next.js answers all of the above
import Counter from './Counter';

export default async function Page() {
  const initial = await fetch('https://api.example.com/count', {
    next: { revalidate: 60 },
  }).then(r => r.json());

  return <Counter initial={initial.value} />;
}

External links

Exercise

List five concrete responsibilities you'd hand to Next.js if you ported a small Vite + React app. For each, write the file or convention you'd use (e.g. routing → app/…/page.tsx).

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue

Comments 0

🔔 Reply notifications (sign in)
Sign inPlease sign in to comment.

No comments yet — be the first.