Consider this Next.js server component that fetches a list of users from an API and renders their names:
export default async function Users() {
const res = await fetch('https://jsonplaceholder.typicode.com/users');
const users = await res.json();
return (
<ul>
{users.map(user => <li key={user.id}>{user.name}</li>)}
</ul>
);
}What will this component render?
export default async function Users() { const res = await fetch('https://jsonplaceholder.typicode.com/users'); const users = await res.json(); return ( <ul> {users.map(user => <li key={user.id}>{user.name}</li>)} </ul> ); }
Think about what the fetch call returns and how the data is used in the component.
The fetch call retrieves the user data from the API. Since this is a server component, the fetch runs on the server, so it works as expected. The component renders a list of all user names inside <li> elements.
Given a server component that fetches data using await fetch(), when does this fetch happen?
export default async function Data() { const res = await fetch('https://api.example.com/data'); const data = await res.json(); return <div>{data.message}</div>; }
Think about how server components behave on each request.
Server components run on the server for each client request, so the fetch runs every time the component is rendered on the server.
Identify which fetch usage will cause a runtime error in a Next.js server component.
export default async function Example() { // Option A const resA = await fetch('/api/data'); // Option B const resB = await fetch('https://api.example.com/data', { cache: 'no-store' }); // Option C const resC = await fetch('https://api.example.com/data', { method: 'POST' }); // Option D const resD = await fetch('https://api.example.com/data', { signal: new AbortController().signal }); return <div>Check console</div>; }
Consider which HTTP methods are allowed in server component fetch calls.
In Next.js server components, fetch supports GET requests by default. Using POST method directly in fetch inside server components causes runtime errors because server components expect data fetching to be idempotent and cacheable.
Look at this server component code:
export default async function Posts() {
const res = await fetch('http://localhost:3000/api/posts');
const posts = await res.json();
return (
<ul>
{posts.map(post => <li key={post.id}>{post.title}</li>)}
</ul>
);
}Why does it fail with TypeError: Failed to fetch when deployed?
export default async function Posts() { const res = await fetch('http://localhost:3000/api/posts'); const posts = await res.json(); return ( <ul> {posts.map(post => <li key={post.id}>{post.title}</li>)} </ul> ); }
Think about what 'localhost' means when deployed on a server.
When deployed, 'localhost' refers to the server itself, which may not have the API running or accessible. The fetch call should use the full public URL or relative path, not 'localhost'.
Choose the best explanation for why fetching data in server components is preferred over client components in Next.js.
Think about where the code runs and how it affects performance and SEO.
Fetching data in server components happens on the server, so the client receives fully rendered HTML. This reduces JavaScript sent to the client and improves SEO because content is available immediately.