NextjsData Fetching Overview

Data Fetching Overview

Data fetching is one of the areas where the App Router differs most sharply from the Pages Router — and, once it clicks, one of the biggest simplifications Next.js has made. Instead of a special page-level function that runs separately from your component, you fetch data with plain async/await directly inside the component that needs it.

Before and after

In the Pages Router, a page and its data were two separate exports that Next.js wired together for you at the framework level.

Pages Router (before) — pages/posts/index.tsx

TSX
export async function getServerSideProps() {
  const res = await fetch('https://api.example.com/posts')
  const posts = await res.json()
  return { props: { posts } }
}

export default function PostsPage({ posts }) {
  return (
    <ul>
      {posts.map((post) => (
        <li key={post.id}>{post.title}</li>
      ))}
    </ul>
  )
}

App Router (after) — app/posts/page.tsx

TSX
export default async function PostsPage() {
  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>
  )
}

No getServerSideProps, no getStaticProps, no props-passing indirection — the component itself is async, and it awaits its own data right where that data is used. Fewer moving parts, and the data requirement lives visibly next to the markup that depends on it.

Two places data fetching happens

Where

How

When to use it

Server Components

async/await directly in the component, plain fetch() or a database/ORM call

The default choice — content that can be rendered on the server, including most pages

Client Components

useEffect + useState, or a library like SWR / React Query

Genuinely interactive, user-specific, or fast-changing data that needs to live in the browser

Both are covered in depth on their own pages — see Fetching in Server Components and Fetching in Client Components. As a rule of thumb, default to fetching on the server; only drop down to the client when you have a concrete reason (interactivity, browser-only state, or data that must refresh while the user watches).

Server Components can skip the API layer entirely
Because Server Components run on the server, they can call a database or an ORM directly — there is no requirement to build a separate API route just to move data from your database to your page. That said, an API layer is still the right call when the same data needs to be consumed by something other than this Next.js app (a mobile client, a public API, a third party).