Next.js Discord

Discord Forum

Big Client & Server component problem

Unanswered
Florida White posted this in #help-forum
Open in Discord
Florida WhiteOP
My colleague and I have nearly finished a large project together. We migrated our application from a Laravel/React stack using Inertia.js to a headless architecture with Next.js (App Router) and Laravel as the backend.

Yesterday, we tried to set up a testing environment and attempted to build the project. During development, everything worked fine locally — we never encountered any major issues. But now, trying to build the project feels like opening a can of endless errors.

The project structure looks like this:

app/
- posts/
page.tsx <--- Entire frontend logic for this route

components/
table.tsx
dropdown.tsx
...etc.


The main issue: we made everything a client component.
I spent the whole day fixing one issue after another — things like "document is not defined", but once I fix one error, the next one appears. Sometimes, even a page that had no errors before suddenly breaks again.

The two most common errors we're facing:
"document is not defined"
"useSearchParams() should be wrapped in a suspense boundary at page..."

Our question:
Is there a solid tutorial or guide that explains how to properly split pages and components between server and client components in Next.js?

At this point, we’re really desperate for anything that could help us move forward.

6 Replies

I don’t think there’s a quick and easy guide to learn all that you need to know about Next.js to be able to solve these problems.

It’s a whole new mental model, Server Components (the default) are the entry points of a page, and Client Componentes should be seen as a kind of plug-in components that you bring into your server components to be able to make use of client-side only features, browser APIs and basically interactivity, but you should try not to make everything a client component.

Your issue of “document is not defined” occurred because Next.js does SSR (Server Side Rendering) of your components, (even client components as an optimization) so when they run on the server the window object does not exist since it’s a Browser API, and document is part of the window API
and for the useSearchParams() problem, this is necessary in Next 15 since SearchParams and other APIs are not marked as dynamic APIs, and by wrapping the components that use these dynamic APIs Next.js can know how to optimize your App.
Wrapping a component that uses
useSearchParams() in <Suspense> lets Next.js go ahead and pre-render as much as your pages that do not depend on request time data (such as search params)
This is the official Next.js course
https://nextjs.org/learn
Florida WhiteOP
@LuisLl thanks.
Whats the best way to re-fetch data using a server component?
For example, the application has a table where data can be edited or deleted inside a modal.
Once a change is made, the table should refresh to reflect the updated data. (Updating just the array isnt a solution, multiple users will use the software)

It feels counterproductive to build a separate function just to re-fetch the data on a client component.
For an app like that you can make use of client components, but try not to make the whole app a client component. Instead, leave the page as a default server component to fetch initial data and pass the initial data down to a client component to handle the rest
@Florida White <@744377057139753020> thanks. Whats the best way to re-fetch data using a server component? For example, the application has a table where data can be edited or deleted inside a modal. Once a change is made, the table should refresh to reflect the updated data. (Updating just the array isnt a solution, multiple users will use the software) It feels counterproductive to build a separate function just to re-fetch the data on a client component.
When you do mutations you can make use of Server Actions. These are basically POST endpoint under the hood with a nice DX and are meant to be used on client components to perform actions like these you described, inside the Server Action you call revalidatePath($ or revalidateTag() and you’ll request the new UI from the server with the latest data.

Also, you can use router.refresh() directly inside the client component to force Next.js to purge the cache and server fresh data. But honestly, handling this fully client side might be better for this use case, with React Query for example