5 questions found
How do you fetch data inside a server component in the App Router?
Beginner
You can simply use async and await directly inside a server component's function body, calling fetch or a database query, since server components run on the server and can handle asynchronous operations naturally before the page is sent to the browser.
export default async function Page() {
const res = await fetch('https://api.example.com/posts');
const posts = await res.json();
return <ul>{posts.map(p => <li key={p.id}>{p.title}</li>)}</ul>;
}
Real-world example
A blog homepage fetches its list of articles directly inside the page component, rendering the full list of posts as static HTML before it ever reaches the visitor's browser.
Common follow-ups: Do you need any special hooks to fetch data in a server component?;How is this different from fetching data in the Pages Router?
Server Components;Caching
How do you fetch data inside a client component that needs to run in the browser?
Beginner
Since client components cannot use async directly in their function body the way server components can, you typically fetch data inside a useEffect hook, storing the result in state with useState, and showing a loading indicator while the request is in progress.
'use client';
import { useEffect, useState } from 'react';
export default function Comments({ postId }) {
const [comments, setComments] = useState([]);
useEffect(() => {
fetch(`/api/posts/${postId}/comments`).then(res => res.json()).then(setComments);
}, [postId]);
return <ul>{comments.map(c => <li key={c.id}>{c.text}</li>)}</ul>;
}
Real-world example
A comments section fetches new comments in the browser whenever the user scrolls to it, since comments update frequently and benefit from being fetched client side after the main page has already loaded.
Common follow-ups: Should this data instead be fetched on the server and passed down as props?;What are the tradeoffs between client side and server side data fetching?
Client Components & Hydration;Server-Side vs Client-Side Data Fetching Patterns
How do you fetch multiple pieces of data in parallel to avoid slow, sequential loading?
Intermediate
You start all your fetch calls first without awaiting each one immediately, collect the resulting promises, and then use Promise.all to wait for all of them to finish together, so the total wait time is roughly as long as the slowest single request instead of the sum of all requests.
export default async function Page() {
const postsPromise = fetch('https://api.example.com/posts').then(r => r.json());
const usersPromise = fetch('https://api.example.com/users').then(r => r.json());
const [posts, users] = await Promise.all([postsPromise, usersPromise]);
return <div>{/* render posts and users */}</div>;
}
Real-world example
A dashboard page fetches the user's profile, recent orders, and notification count all at the same time using Promise.all, instead of waiting for each request to finish one after another, cutting the total load time significantly.
Common follow-ups: What happens if one of the parallel requests fails while the others succeed?;How does this pattern work together with Suspense and streaming?
Loading UI & Streaming with Suspense;Caching
How can you pass data fetched on the server down into a client component?
Intermediate
You fetch the data inside a server component as usual, and then pass the resulting data as a normal prop to a client component that you render as its child, letting the client component focus purely on interactivity while the server handles the actual data loading.
export default async function Page() {
const post = await getPost();
return <LikeButton initialLikes={post.likes} postId={post.id} />;
}
Real-world example
A blog post page fetches the current like count on the server and passes it as a starting value to a client side like button, which then handles further updates interactively in the browser.
Common follow-ups: What kinds of data can safely be passed from server to client components?;Can you pass a database connection object as a prop this way?
Client Components & Hydration;Server Components
What is request deduplication in Next.js, and how does it help with data fetching?
Advanced
Request deduplication automatically combines multiple identical fetch calls made during the same render into a single actual network request, so if several components on the same page happen to request the exact same data, Next.js only fetches it once and shares the result, avoiding unnecessary duplicate work.
// Even if called in multiple components during the same render,
// this fetch is only actually executed once
async function getUser(id) {
const res = await fetch(`https://api.example.com/users/${id}`);
return res.json();
}
Real-world example
A product page calls a shared getUser function from both the header and the sidebar components, and thanks to request deduplication, only a single network request is actually made even though the function was called twice.
Common follow-ups: Does request deduplication work across different pages or only within a single render?;How does this interact with the fetch cache options like no-store?
Caching;Server Components