1. Data Fetching Strategies
Next.js offers several methods to fetch data, each suited for different use cases:
a. Static Site Generation (SSG)
Use
getStaticPropsto fetch data at build time.Ideal for content that doesn’t change often (e.g., blog posts, product catalogs).
// pages/posts/index.js
export async function getStaticProps() {
const res = await fetch('https://api.example.com/posts');
const posts = await res.json();
return { props: { posts } };
}
export default function PostsPage({ posts }) {
return (
<ul>
{posts.map(post => (
<li key={post.id}>{post.title}</li>
))}
</ul>
);
}b. Dynamic Paths with getStaticPaths
Use alongside
getStaticPropsto generate pages for dynamic routes.
// pages/posts/[id].js
export async function getStaticPaths() {
const res = await fetch('https://api.example.com/posts');
const posts = await res.json();
const paths = posts.map(post => ({ params: { id: post.id.toString() } }));
return { paths, fallback: 'blocking' };
}
export async function getStaticProps({ params }) {
const res = await fetch(`https://api.example.com/posts/${params.id}`);
const post = await res.json();
return { props: { post } };
}c. Server-Side Rendering (SSR)
Use
getServerSidePropsto fetch data on every request.Best for highly dynamic data (e.g., user dashboards).
export async function getServerSideProps(context) {
const res = await fetch('https://api.example.com/user', { headers: { cookie: context.req.headers.cookie } });
const user = await res.json();
return { props: { user } };
}d. Incremental Static Regeneration (ISR)
Add
revalidatetogetStaticPropsto update static pages after a given interval.Combines SSG performance with dynamic content updates.
export async function getStaticProps() {
const data = await fetchData();
return {
props: { data },
revalidate: 60, // regenerate at most once every 60 seconds
};
}e. Client-Side Data Fetching
Use the
swrhook for client-side fetching and caching.
import useSWR from 'swr';
function Profile() {
const { data, error } = useSWR('/api/user', fetcher);
if (error) return <div>Failed to load</div>;
if (!data) return <div>Loading...</div>;
return <div>Welcome, {data.name}!</div>;
}2. Advanced Dynamic Routing
File-based routing in Next.js allows powerful patterns out of the box:
a. Basic Dynamic Routes
Create a file like
pages/products/[slug].jsto handle routes such as/products/hat.
b. Catch-All Routes
Use
[...params].jsto match multiple segments:pages/docs/[...slug].jswill match/docs/a/b/c.
c. Optional Catch-All Routes
Use
[[...params]].jsto make catch-all segments optional, matching both/blogand/blog/a/b.
d. Nested Routes
Organize pages into subfolders for readability:
pages/dashboard/settings/profile.js.
3. Preview Mode
Enable Preview Mode to toggle between draft and published content in SSG pages:
// pages/api/preview.js
export default function handler(req, res) {
res.setPreviewData({});
res.redirect(req.query.redirect || '/');
}In your page:
export async function getStaticProps({ preview }) {
const data = await fetchPosts({ draft: preview });
return { props: { data } };
}With these techniques, you can fetch and render data in Next.js with flexibility and performance, tailoring each page to your application’s needs. In the next chapter, we’ll dive into styling and theming strategies in Next.js.