Fetching Data
In a Server Component you can fetch data with a plain async function — no useEffect, no loading flicker.
What you will learn
- Fetch data in an async Server Component
- Use await with fetch
- Compare it to the old useEffect way
Fetching the old React way
In plain React you fetch inside useEffect, store the result in state, and show a loading spinner while you wait. It works, but it means an empty page flashes first, and search bots see nothing.
Fetching the Next.js way
Because Server Components run on the server, you can make the component itself async and simply await your data before the page is sent. No useEffect, no spinner, and the HTML arrives already filled in.
// app/users/page.js (a Server Component)
export default async function UsersPage() {
const res = await fetch('https://jsonplaceholder.typicode.com/users');
const users = await res.json();
return (
<ul>
{users.map((u) => (
<li key={u.id}>{u.name}</li>
))}
</ul>
);
}Note: Output: Leanne Graham Ervin Howell Clementine Bauch ... (10 names) The data was fetched on the server, so the list is already in the HTML when the page loads. No loading spinner and no empty flash.
The whole fetch flow, step by step
A fetch is just your code asking another web address for some data (an HTTP request — the standard way one program asks another for information over the internet) and getting an answer back. Here is exactly what happens, in order, when someone visits /users:
- A visitor opens
/usersin the browser. The browser asks your Next.js server for that page. - On the server, Next.js runs your
UsersPagefunction. Because it isasync, it is allowed to pause and wait. - It hits
await fetch(...): the server sends an HTTP request to the users address and waits for the reply. - The reply comes back as raw text.
await res.json()turns that text into a real JavaScript array of user objects. - Now that the data is ready, the component builds the
<ul>list of names — the page is rendered with the data already inside it. - The server sends that finished HTML to the browser. The visitor sees the full list immediately — no spinner, and search bots see the names too.
| Plain React (useEffect) | Next.js Server Component | |
|---|---|---|
| Where it runs | Browser | Server |
| Needs useState/useEffect | Yes | No |
| Loading flicker | Usually | No — data is ready first |
| Good for SEO | No | Yes |
Next.js also caches fetch results by default, so repeated requests are fast. You can control freshness with options like fetch(url, { next: { revalidate: 60 } }) to re-fetch at most once a minute.
Tip: Only Server Components can be async like this. If you need to fetch from a Client Component (after a click, say), you still use the useEffect pattern you already know.
Watch out: Do not put your secret API keys in a Client Component — they would be shipped to the browser. Fetch with secrets in a Server Component, where the key stays safely on the server.
Q. How do you fetch data in a Next.js Server Component?
✍️ Practice
- Fetch and list posts from
https://jsonplaceholder.typicode.com/postsin an async page. - Show the first 5 results only by slicing the array.
🏠 Homework
- Build a page that fetches a list of users on the server and renders their names and emails.