Recently, I tried using React Suspense in a Next.js project, only for me to discover that there is no support for Suspense in Next.js — or at least the pages directory.
If you're using the appDir of Next.js, this support is extended, as there's a feature, Streaming and Loading UI that is built on top of React Suspense.
I use the pages directory for all of my projects, and I needed to really use Suspense. But, every time I try doing that, I'll get an error like the one below.
Error: Fallback data is required when using suspense in SSR
For a while, I couldn't wrap my head around why this error kept showing up. To make matters worse, I was using SWR too, and their docs also specified that using <Suspense>
in data frameworks like SWR isn't recommended.
They went on to talk about the drawback of accomplishing this in SSR frameworks like Next.js too. When I saw this, I was just weak — nonetheless, I pressed on.
After scouring the internet vainly, I finally stumbled upon Ali Bentaleb's article on how to use Suspense with next/dynamic, since it — next/dynamic
— is a bit similar to React.Lazy()
.
He also suggested the use of React concurrent mode by updating your next.config.js
file with the snippet below.
I tried this approach, and I still do not know why it didn't work as expected. Later on, I realized it could be because I didn't include the concurrentFeatures
property in my config.
The snippet below was what worked for me. If you take a closer look, you'll notice that I added the ssr
property and set its value to false
, and because I use SWR, I set the suspense value to true
in the config
There's one catch with this approach though. By setting ssr: false
, I'm deferring the rendering of the component to the client-side, which can potentially impact the initial load time and SEO considerations.
But, since this route is a protected one — a user dashboard — The SEO caveat can be ignored.
If you want to use suspense on a page that is SEO dependent, I'll suggest that you make use of the concurrentFeatures
approach that Ali suggested in his article
You can also learn more about Suspense and Server-Side Rendering in this GitHub issue if you want to — because some errors can vary depending on our use cases.
A potential fix
One thing I realized after using this approach where i had to disable ssr
by setting its value to false
is that, upon refreshing or reloading the page, the error still persists.
Sometimes it shows up in production where the page is black with an error similar to the one below
A client-side exception occured. check the browser console for...
So many issues were brought up regarding React Suspense in Next.js. Although, the Next.js team offered a workaround for using Suspense
with React.lazy()
instead of next/dynamic
.
This Pull Request covers everything they fixed regarding Suspense. Take a look, when you can.
I stumbled upon another clue that seemed like a fix — and yes, it became one on the long run. It was suggested by Kota Zhang in this discussion.
This approach suited my usecase because I had data that keeps on chnaging at differnet intervals. If you happen to be using a data-heeavy library like SWR, you may undertand why this keeps happening.
It is somewhat related to how the data changes, and what is rendered on the client is different from that of the server.
Hence, appending a unique key
property to the Suspense component to distinguish these renders would suffice. In the snippet below, I employed randomUUID
from the crypto
module in Typescript.
If you're not using Typescript, you may have to install the module/package.