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
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
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).