Fetching data in server components lets your app get information before showing the page. This makes pages load faster and work better for users.
Fetch in server components in NextJS
Start learning this pattern below
Jump into concepts and practice - no test required
export default async function Page() { const res = await fetch('https://api.example.com/data'); const data = await res.json(); return ( <main> <h1>Data:</h1> <pre>{JSON.stringify(data, null, 2)}</pre> </main> ); }
Use await fetch() inside an async server component function.
Server components run only on the server, so you can safely fetch data here.
export default async function Page() { const res = await fetch('https://api.example.com/users'); const users = await res.json(); return <div>{users.length} users found</div>; }
export default async function Page() { 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> ); }
export default async function Page() { const res = await fetch('https://api.example.com/data', { cache: 'no-store' }); const data = await res.json(); return <div>Fresh data loaded every time</div>; }
This server component fetches a todo item from a public API and shows its title and completion status.
export default async function Page() { const res = await fetch('https://jsonplaceholder.typicode.com/todos/1'); const todo = await res.json(); return ( <main> <h1>Todo Item</h1> <p><strong>Title:</strong> {todo.title}</p> <p><strong>Completed:</strong> {todo.completed ? 'Yes' : 'No'}</p> </main> ); }
Server components run only on the server, so you cannot use browser-only APIs here.
Use cache: 'no-store' in fetch options to disable caching if you want fresh data every time.
Fetching in server components helps keep API keys safe because code does not run in the browser.
Fetch data inside async server components using await fetch().
Server components run on the server, so data is ready before the page shows.
This improves speed and security by keeping data fetching away from the browser.
Practice
fetch() call to get data before rendering?Solution
Step 1: Understand server components run on the server
Server components execute on the server before sending HTML to the browser, so data fetching happens here.Step 2: Use
Usingawait fetch()inside async server componentsawait fetch()directly inside an async server component fetches data before rendering.Final Answer:
Directly inside the async server component usingawait fetch()-> Option CQuick Check:
Fetch in async server component = Directly inside the async server component usingawait fetch()[OK]
- Trying to fetch data inside client hooks like useEffect
- Fetching data in React state hooks which run on client
- Assuming API routes are mandatory for server component fetch
Solution
Step 1: Use await with fetch to wait for response
Fetch returns a promise, so useawaitto wait for it to resolve.Step 2: Call
After fetch resolves, callres.json()on the response to parse JSONres.json()to get the parsed data, also awaited or chained with then.Final Answer:
const data = await fetch('https://api.example.com/data').then(res => res.json()) -> Option AQuick Check:
Await fetch then parse JSON = const data = await fetch('https://api.example.com/data').then(res => res.json()) [OK]
- Forgetting to await fetch causing unresolved promises
- Calling .json() directly on fetch without awaiting response
- Using fetch without handling the response parsing
export default async function Page() {
const res = await fetch('https://jsonplaceholder.typicode.com/todos/1');
const todo = await res.json();
return {JSON.stringify(todo)};
}Solution
Step 1: Await fetch and parse JSON in server component
The code correctly awaits fetch and then awaits res.json() to get the todo object.Step 2: Return JSON stringified todo inside <pre> tag
The component returns a <pre> element with the stringified todo data, so it renders the JSON text.Final Answer:
<pre>{"userId":1,"id":1,"title":"delectus aut autem","completed":false}</pre> -> Option AQuick Check:
Await fetch + JSON.stringify output ={"userId":1,"id":1,"title":"delectus aut autem","completed":false}[OK]
- Expecting fetch to fail in server components
- Not awaiting fetch causing unresolved promises
- Returning raw object instead of stringified JSON
export default function Page() {
const res = await fetch('https://api.example.com/data');
const data = await res.json();
return <div>{data.title}</div>;
}Solution
Step 1: Check async usage in server component
The component uses await but is not declared async, which causes a syntax error.Step 2: Confirm fetch is allowed in server components
Fetch is allowed in server components, so no error there. Also, res.json() returns a promise, so awaiting is correct.Final Answer:
Missing async keyword on the component function -> Option BQuick Check:
Await requires async function = Missing async keyword on the component function [OK]
- Forgetting async on function using await
- Thinking fetch is disallowed in server components
- Misunderstanding res.json() returns a promise
Solution
Step 1: Understand parallel fetching improves performance
Fetching user and posts in parallel with Promise.all reduces total wait time compared to sequential awaits.Step 2: Use Promise.all inside async server component to fetch both
Inside the async server component, useconst [user, posts] = await Promise.all([fetchUser(), fetchPosts()])to fetch simultaneously.Step 3: Render user name and post titles after both fetches complete
After both promises resolve, render the data together efficiently in the server component.Final Answer:
Fetch user and posts in parallel using Promise.all inside the server component -> Option DQuick Check:
Parallel fetch with Promise.all = Fetch user and posts in parallel using Promise.all inside the server component [OK]
- Fetching data sequentially causing slower load
- Mixing client and server fetching unnecessarily
- Nesting fetch calls causing callback delays
