6/27/2024, edited 7/3/2024

Limitations of next.js SSR

🍰

The 13th generation of next was advertised as an ultimate solution, that among other things will make it possible to mix client and server components freely. I’ve tried it and even described my experience in this article from December 2023. At that point, I’ve noticed that there are some strange warnings, but I didn’t pay attention, as it seemed like some minor issues to me. However, when I tried it again in a commercial project, I’ve found out, that the warning is quite important, as it says that I’m attempting to do something that is not supported.

Here’s an example of such a warning:

clientWrapper.tsx:27 Warning: Cannot update a component (`Router`) while rendering a different component (`ClientWrapper`).
To locate the bad setState() call inside `ClientWrapper`,
follow the stack trace as described in https://reactjs.org/link/setstate-in-render

This problem appears when one calls the server component inside a client component, like that:

function ClientComponent({ ServerComponent }) {
  return (
    <>
      <Suspense fallback={'loading'}>
        <ServerComponent />
        // or {ServerComponent()}
      </Suspense>
    </>
  );
}

The doc says, that the supported pattern is:

Passing Server Components to Client Components as Props

However, it is true only if you call the component on a server, and pass the result to the client component, like that:

function ClientComponent({ serverComponentResult }) {
  return (
    <>
      <Suspense fallback={'loading'}>{serverComponentResult}</Suspense>
    </>
  );
}

It may seem like a minor issue at first glance, right? What’s the difference after all? Well, so what about a server component, that requires props from a client?

There’s already a topic for that at reddit, and it seems that majority agrees on using API instead, just like for SPAs. You can of course use next’s actions as well, but it’s an API meant for mutations, so for me, it seems even worse.

So I feel slightly disappointed, as I was hoping for experience similar to Hotwire and LiveView, so as a part of the famous component streaming feature I would be able to get a prerendered component from a server on a client side, instead of calling API and doing all the dance.

So is it all lost? Actually, I’m not so sure. Let’s take a step back for a minute. I’ve already mentioned, that there’s a warning, but still the thing works.

Moreover, I spent some time and managed to get rid of the warnings, and also some other issues that I haven’t mentioned here. You can find the code here. I’m totally aware that it’s ugly, just like any other workaround, but the point is that it still works, which makes me think that maybe it will be officially supported at some point in the future.

So I keep my fingers crossed, so we can push the boundaries and write the code in a way that suits as best.

Cheers 🖖