Learn different methods of fetching data in Next.js
Fetching data on the client using SWR or React Query
import useSWR from 'swr'
function Profile() {
const { data, error, isLoading } = useSWR('/api/user', fetcher)
if (error) return Failed to load
if (isLoading) return Loading...
return (
Hello {data.name}!
Role: {data.role}
)
}
// Global SWR configuration
export const SWRConfig = {
fetcher: (url) => fetch(url).then((res) => res.json()),
revalidateOnFocus: false,
revalidateOnReconnect: true
}
import { useQuery } from '@tanstack/react-query'
function TodoList() {
const { data, isLoading, error } = useQuery({
queryKey: ['todos'],
queryFn: () => fetch('/api/todos').then((res) => res.json())
})
if (isLoading) return Loading todos...
if (error) return Error: {error.message}
return (
{data.map((todo) => (
- {todo.title}
))}
)
}
Fetching data at request time
// pages/dashboard.tsx
export default function Dashboard({ user, analytics }) {
return (
Welcome back, {user.name}
Views: {analytics.views}
Conversions: {analytics.conversions}
)
}
export async function getServerSideProps(context) {
// Check authentication
const session = await getSession(context)
if (!session) {
return {
redirect: {
destination: '/login',
permanent: false,
},
}
}
// Fetch data
const user = await fetchUser(session.userId)
const analytics = await fetchAnalytics(user.id)
return {
props: {
user,
analytics,
},
}
}
// pages/api/analytics.ts
import { NextApiRequest, NextApiResponse } from 'next'
import { getSession } from 'next-auth/react'
export default async function handler(
req: NextApiRequest,
res: NextApiResponse
) {
const session = await getSession({ req })
if (!session) {
return res.status(401).json({ error: 'Unauthorized' })
}
const analytics = await prisma.analytics.findMany({
where: { userId: session.user.id },
orderBy: { date: 'desc' },
take: 7
})
res.status(200).json(analytics)
}
Pre-rendering pages at build time
// pages/blog/[slug].tsx
export default function BlogPost({ post }) {
return (
{post.title}
)
}
export async function getStaticPaths() {
const posts = await getAllPosts()
const paths = posts.map((post) => ({
params: { slug: post.slug }
}))
return {
paths,
fallback: 'blocking'
}
}
export async function getStaticProps({ params }) {
const post = await getPostBySlug(params.slug)
return {
props: { post },
revalidate: 60 // ISR: update every minute
}
}
// pages/api/revalidate.ts
export default async function handler(req, res) {
// Check for secret to confirm this is a valid request
if (req.query.secret !== process.env.REVALIDATE_TOKEN) {
return res.status(401).json({ message: 'Invalid token' })
}
try {
// Revalidate the home page
await res.revalidate('/')
// Revalidate a blog post
await res.revalidate(`/blog/${req.query.slug}`)
return res.json({ revalidated: true })
} catch (err) {
return res.status(500).send('Error revalidating')
}
}