javascript 37 lines · 6 steps

An intercepted photo modal route in Next.js

An async server component fetches a photo by id, sets its page metadata, and renders it inside a modal.

Explained by highlit
1import { notFound } from 'next/navigation'
2import { getPhotoById } from '@/lib/photos'
3import Modal from '@/components/modal'
4import Image from 'next/image'
5 
6export async function generateMetadata({ params }) {
7 const { id } = await params
8 const photo = await getPhotoById(id)
9 if (!photo) return {}
10 return { title: photo.title }
11}
12 
13export default async function PhotoModal({ params }) {
14 const { id } = await params
15 const photo = await getPhotoById(id)
16 
17 if (!photo) notFound()
18 
19 return (
20 <Modal>
21 <figure className="photo-modal">
22 <Image
23 src={photo.url}
24 alt={photo.title}
25 width={photo.width}
26 height={photo.height}
27 sizes="(max-width: 768px) 100vw, 768px"
28 priority
29 />
30 <figcaption>
31 <h2>{photo.title}</h2>
32 <p>by {photo.author}</p>
33 </figcaption>
34 </figure>
35 </Modal>
36 )
37}
01 / 01
STEP 01

Walkthrough

Space play ←→ step click any line
Three takeaways
  1. 1Async server components can await params and fetch data directly before rendering.
  2. 2generateMetadata and the page component share the same data-fetching logic to stay consistent.
  3. 3Calling notFound() short-circuits rendering into the framework's 404 handling for missing records.

Related explainers

Share this explainer

Here's the card — post it anywhere.

An intercepted photo modal route in Next.js — share card
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code