Fetching Data
In traditional React setups, developers usually fetch data utilizing useEffect combined with libraries like axios or Redux. In modern Next.js using the App Router, data fetching occurs securely inside Server Components.
Server-Side Fetching
Since Server Components execute in node environments, you can write asynchronous functions directly at the component root level. You do not need to manage loading states manually (like isLoading) because the component awaits the data natively before returning the HTML.
// app/users/page.tsx
async function getUsers() {
// This runs securely on the backend server
const res = await fetch('https://api.example.com/users');
if (!res.ok) throw new Error('Fetch failed');
return res.json();
}
export default async function UserPage() {
// The component pauses here while data is fetched
const users = await getUsers();
return (
<ul>
{users.map(user => (
<li key={user.id}>{user.name}</li>
))}
</ul>
);
}
Native fetch Caching
Next.js patches the native global fetch command to add complex caching parameters globally. By default, fetch requests are heavily cached during build time (SSG behavior).
You can disable caching natively to force SSR dynamic data processing.
// Force the fetch to run on every single pageload
const res = await fetch('https://api.example.com/live-stock', {
cache: 'no-store'
});
You can execute Incremental Static Regeneration (ISR) heavily by assigning a specific timed interval to the fetch caching parameters.
// Cache the fetch results for exactly 60 seconds
const res = await fetch('https://api.example.com/blog-posts', {
next: { revalidate: 60 }
});