Course outline · 0% complete

0/29 lessons0%

Course overview →

Async server components

lesson 4-1 · ~12 min · 11/29

Quiz

Warm-up from 'Two kinds of components': which of these can a server component do that a client component cannot?

Just await it

Remember the data-fetching dance from the React course? useEffect, a loading flag, an error flag, a state setter. In a server component the whole ceremony collapses into await:

// app/blog/page.js
export default async function BlogPage() {
  const res = await fetch("https://api.example.com/posts");
  const posts = await res.json();
  return (
    <ul>
      {posts.map((post) => (
        <li key={post.id}>{post.title}</li>
      ))}
    </ul>
  );
}

Decode it:

  • The component itself is async. Server components may be, client components may not.
  • No useEffect, no loading state variables. The server simply waits for the data, renders, and sends finished HTML.
  • Because this runs on the server, the API call could just as well be a direct database query, like the ones you wrote in Backend with Node.js.

Worked example: skip the HTTP hop

Because a server component already runs on the server, calling your own API over HTTP from it is a wasted round trip — the request would leave your server just to come back in. Query the data source directly instead:

// app/blog/page.js
import { db } from "../lib/db";

export default async function BlogPage() {
  const posts = await db.query("SELECT id, title FROM posts ORDER BY created_at DESC");
  return (
    <ul>
      {posts.map((post) => (
        <li key={post.id}>{post.title}</li>
      ))}
    </ul>
  );
}

Decode it:

  • This is the exact query code you wrote in Express handlers in Backend with Node.js, now living inside the component that renders the result.
  • It is safe because server components never ship their code to the browser (Unit 3), so the connection string stays secret.
  • Keep fetch for external APIs (someone else's server). For your own database: query directly.

Fetch where you need it

A worry from the React course: 'should I fetch at the top and drill props down?' In server components the answer is fetch inside the component that needs the data. Next.js memoizes identical fetch calls during one render pass, so if three components on the page request the same URL, only one real network request happens.

That memoization lasts for a single render of a single request. It is not a cache that survives between visitors, which is the subject of the next lesson.

Quiz

A server component needs data that lives in your own Postgres database. What is the recommended way to get it?

Quiz

During one page render, a Header component and a Sidebar component both call fetch("https://api.example.com/user/7"). How many real network requests are made?