Next.js Discord

Discord Forum

Server Side Rendering related issue. someone please help....

Answered
RoronoaHemesh posted this in #help-forum
Open in Discord
Avatar
So I am using app routing in a practice project. I have created an unsplash clone in which there a route name 'list' and in this route, the trending images of the actual unsplash site's homepage is being rendered using the unsplash API (https://api.unsplash.com/photos/?client_id=K5g3fmM9e2BwevkhVmW4tjtkX9p36SYGWut87KZolxw&page=1&per_page=12). Now what I want is that the images should be first rendered on the server side and I somehow managed to do the SSR of these images. But the problem is that if I want to have any kind of client interactivity on this page, then I have to make this page a client side component by using the "use client" string. And now since this page has become a client side component, It becomes problematic to render the data on the server and insted I have to render the data on the front-end which slows the process. I read documentation on nextjs.org about data fetching in app router and found a function called "use" that accepts a promise and is similar to await. And it does aloows to fetch data on the server but an error pops up if I try to use hooks or pagination on this page. I have shared an SS of the error that pops on the browser if I try to use a client component while trying to render the data on the server side.
Image
Answered by Julienng
You need to split components that need interactivity from your page to handle use client directive if you don't want the full page to be a client component.

If you really need interactivity on the full page, you can do something like that
// keep the page RSC
const TrendingImagesPage = () => {
  // your server logic...

  return (
    // create a Page client component that accept children or a props ReactNode
    <TrendingImageClientComponent image={<ImageRenderedRSC />}>
       <ImageRenderedRSC /> 
    </TrendingImageClientComponent>
  )
}


Or you can use forms if it's enough to handle the reactivity (https://nextjs.org/docs/app/building-your-application/data-fetching/server-actions)
View full answer

8 Replies

Avatar
You need to split components that need interactivity from your page to handle use client directive if you don't want the full page to be a client component.

If you really need interactivity on the full page, you can do something like that
// keep the page RSC
const TrendingImagesPage = () => {
  // your server logic...

  return (
    // create a Page client component that accept children or a props ReactNode
    <TrendingImageClientComponent image={<ImageRenderedRSC />}>
       <ImageRenderedRSC /> 
    </TrendingImageClientComponent>
  )
}


Or you can use forms if it's enough to handle the reactivity (https://nextjs.org/docs/app/building-your-application/data-fetching/server-actions)
Answer
Avatar
Or split only the components that need interactivity :

// keep the page RSC
const TrendingImagesPage = () => {
  // your server logic...

  return (
    // create a page store that handle the state of your client components for that page if you need to share state with multiple client component (shared with a context)
    <TrendingPageStore>
      {/* your component markup */}
       <ImageRenderedRSC />
       {/* it use context to have its state from TrendingPageStore, or not if it doesn't need to be shared
         * by other client components 
         */}
       <ClientValidationButton />
    </TrendingPageStore>
  )
}
Avatar
Yeah thanks bud, I will definitely try splitting out the components that needs interactivity. Just one last question - Suppose I have a page.js file and we know in next js 13, a component is by fefault a server side component. So, this page.js is a server side component by default and in this component, if I import and use an another component which is a client side component for some reason, will it make my page.js a client side component just by importing an another component in it which is a client side component?
Avatar
No problem using client component from server one, it keeps the boundary between components just fine
Using a server component from a client component works too if you pass it through children like that : <Client><ServerOne/></Client>
(you can't import directly a server one in a client component)
Avatar
So for the example before, the render looks like that:
// page.js
// RSC component : server rendered only 
const TrendingImagesPage = () => {

  return (
    <TrendingPageStore>           {/* client: server rendered first and send to client  */}
       <ImageRenderedRSC />       {/* RSC : server rendered only */}
       <ClientValidationButton /> {/* client: server rendered first and send to client  */}
    </TrendingPageStore>
  )
}
Avatar
alright. thanks a lot ❤️