When I was trying to generate a PDFDownloadLink for TripTime, I got this error:

PDFDownloadLink is a web specific API. Or you’re either using this component on Node, or your bundler is not loading react-pdf from the appropiate web build.

As the author of react-pdf explained in this issue:

This happens when next.js renders the page server side. You cannot do that, since what does is creating a blob file on the browser with the PDF content.

Up to now I have learnt two ways to prevent Next.js Server Side Rendering:

Use next js dynamic import with ssr disabled

According to Next.js document:

Next.js supports ES2020 dynamic import() for JavaScript. With it you can import JavaScript modules (inc. React Components) dynamically and work with them. They also work with SSR.

This is what my teammate used for importing the leaflet map too:

1
2
3
4
5
import dynamic from 'next/dynamic';

const TripMapNoSSR = dynamic(() => import('../components/map/TripMap'), {
ssr: false,
});

Use hooks to prevent SSRing

This is shared by a alexcaulfield in the same issue and I reckon this could be used in many scenarios to prevent SSR, not limited to importing.
So I wrote my code based on his idea:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import React, {useEffect, useState} from 'react';

import MyDocument from '../../../components/pdf/TripDocument';
import {PDFDownloadLink, PDFViewer} from "@react-pdf/renderer";

export default function Pdf() {
const [isClient, setIsClient] = useState(false);
useEffect(() => {
setIsClient(true)
}, []);

return <>
{isClient && <PDFDownloadLink document={<MyDocument/>} fileName='somename.pdf'>
{({blob, url, loading, error}) =>
loading ? 'Loading document...' : 'Download now!'
}</PDFDownloadLink>
}
</>
}

worked nice: