Next.js Discord

Discord Forum

Render as a server component but then render as a client component

Unanswered
Philippine Crocodile posted this in #help-forum
Open in Discord
Philippine CrocodileOP
I'm having a hard time wrapping my head around server & client components, and how they work together.

The usecase is:
I have a server component that fetches data and passes the data down to a series of components. The components do not use any 'client' methods so they are rendered in the server as well (correct me if I'm wrong!). Once finished, the rendered server component is sent over the wire and painted on screen.

Now, in the browser, if the user updates certain parts of the webpage, can the server components behave like client components, in the sense that they don't need to re-render on the server, they take in the modified data produced on the client side, and re-render based on that?

I've tried creating a component with useEffect but that automatically makes it non-server component. I also tried creating a context provider but the component that uses it also is a non-server component.

I guess when it comes down to it, is there a cross-over between server & client component? Once a component is either/or, is it always either/or?

102 Replies

Now, in the browser, if the user updates certain parts of the webpage, can the server components behave like client components
what do you mean by "updating certain parts of the webpage"?
ideally in the app router, you can use server components + server actions (for data mutation) and you revalidate cache to get your updated UI refreshed
Philippine CrocodileOP
What I mean is that the webpage consists of a mix bag of client & server components. The user will interact with the client components to handle form inputs and what not. The data that the user is creating needs to be passed to the server components (that are on the same page) and render the client produced data.

What you are saying is, to re-render the server component from the user created data, the client component triggers a server action that re-renders the server component? (correct me if im wrong. im trying to understand this client-server flow)
yeah, that's correct I think
server action mutates data and then re-render your server component
Philippine CrocodileOP
got it.
yeah. so is there a way/method that does it differently?
the client compoentent just passes updated data to the server component without triggereing a http request? The server component's for the most part are kinda just 'displaying data' aside from the initial render
so you are thinking of just updating the data through server action and render new data on the client with state changes?
Philippine CrocodileOP
the user interaction is such that new data is rendered on the client side, avoiding calling server action to re-render server component
not only to re-render server component, but you anyway need to update DB or something?
Philippine CrocodileOP
not yet. the first part is just to display the new data to the user as they create it. Then, later on in the workflow, send the new data to the server.
here is my mental model of this process:
1. webpage renders a mix of client & server components
2. client components take input, generate new data
3. server components need to display the new data
- how to get the new data into the server components without creating a HTTP request?
oh I see, so you are not using any DB. then you will lose your new data by refreshing the window?
if it's OKAY yet then here are the solutions
create new dom elements on the client end by states - don't need to hit backend for your new data
as long as you don't update/use db yet
Philippine CrocodileOP
as the client creates new data, create new DOM elements (compoents) that display the new data?
& replace the server components with the new DOM elements?
not replacing the server components but append new dom elements as you create a new data
Philippine CrocodileOP
so i can't resuse the server component, correct? there isn't a way that a server component can re-render on the client.
Nope, server components are rendered on the server and streamed to the client end
I think in your case, using client components will be better
so you pass data to the client component and you have that data as initial states
and when user adds new data, you change the state to update the UI
Philippine CrocodileOP
suppose
1. page.tsx fetches db data and passes data down (server component)
2. client component receives data and renders on the browser (initial data)
3. user interacts with client components, creates new data, and client component re-renders
4. when user is done, server action to post the new data & persist to database
Philippine CrocodileOP
sorry. misread what you meant.
we do have a database. It is used to fetch data initially.
but during the flow on the browser it is only used again at the end, not in the 'middle' of the flow
what do you mean by mmiddle of the flow?
you mean by adding lots of items for example?
you want to update db at the end of adding items? not after adding an item?
Philippine CrocodileOP
yes. the middle part is the user interactivity, creating new data, displaying new data.
and then at the end, save the new data but not during
then perhaps you may need "Save" button as long as you don't store new items right after adding it?
imagine you added an item, you refresh the page, what should you see?
Philippine CrocodileOP
it depends on how the components are implemented, right?
In my case, I am investigating if the server components can take client component inputs, and re-render instead of making a HTTP request to re-render.

in our usecase, before a page refresh happens, they'll see an alert messaging them that a page refresh will make them start over (ie. lose data).
server components take client component inputs? No server components are pre-rendered on the server
if you don't make any request to the server, server components won't be updated
Serbian Hound
whats actually the problem? @Philippine Crocodile what you want to do sounds very simple
not saying it rudely :p
Philippine CrocodileOP
ok. let's take a step back.
I have a page.tsx that has many components, both server & client components.
The page.tsx fetches initial data from the database and passes that data to the components that need it.
Server components just render the initial data on the server and ...
well @Philippine Crocodile let's summarize
render list of items using server components (initial data)
and then have a client componet with create form and states (this is for new data you create)
and when you add a new item, add it to your state and render new items on your client side
you can use the same component in your server/client component (for example list item)
and you must have your "save" button to store new data in your db, right?
at that point call the server action to update your db - You still need to revalidate the cache
Serbian Hound
list of items will be a server component, the form is a client component, and the 'save' is a server action in this case
Philippine CrocodileOP
i think the answer here is that once a server component always a server component. A server component it seems cannot implement any clientside hooks. A server component is only reactive when triggered via some serverside event (action).

to expand on your list item example, if the list items initially renders on the server, then the only way to update the list item is through server actions (correct?) The client needs to call the server action to update the server component?
yeah, correct
as long as you don't want to update db everytime a user add an item
Serbian Hound
You can pass a function down to the client component to re-fetch on the server component in this case @Philippine Crocodile
but yeah a server component is a server component, a client is a client one
there's no 'blend'
that's why I suggest to have a client component for create form + new list of items that users added
Serbian Hound
yup that makes snese
so this list of new items are server client components they are managed by states - you don't need to hit server yet
and when you click on "save" or "submit" you can call server action to store your new items
Philippine CrocodileOP
ok. i think that is where my mental model was broken. I thought you can render a server component with useEffect with the render-once empty array parameter, such that the server component renders initially on the server, and when it get's painted on the browser, the useEffect runs and registers client side inputs.
Serbian Hound
you could even just update it on the client state if the server-action is sucesssful, all depends how you want to do it
nah useEffect is always always on a client
sever is stateless
@Philippine Crocodile what about my suggestion btw? it's a good approach if you don't want to call server action everytime you create a new item
and do batch saving
Philippine CrocodileOP
got it got it. yeah. the solutions I found online follow your recommendations. But I was wondering why not do it the other way, well, its because you can't!!
Serbian Hound
you can also render server components within client components
haha yeah, because you can't use hooks in server components
Serbian Hound
so it all works out
Like I have a <SessionProvider> context that wraps my app which is on the client, but loads of server components inside it
@Serbian Hound it's not related to OP's problem I think
Philippine CrocodileOP
appreciate the patience. the new react mental model is throwing me in a loop.
Serbian Hound
yeah just saying because he is not understanding the model
its ok @Philippine Crocodile you will get it
Philippine CrocodileOP
@Serbian Hound the server components won't be able to use the context data, right?
Serbian Hound
nope
so you're correct yeah
@James4u sever is stateless
Stateless
Philippine CrocodileOP
stateless. 👍
@Philippine Crocodile even with correct model, if you want batch update, you still need client components
as I described earlier
Philippine CrocodileOP
i guess we can wait for React 20 to have server components become client compoents 😉
@James4u good to know.
Serbian Hound
technically i think you could make the form a server component as long as you dont use useState and useEffect etc
he needs
he didn't want to call server action everytime he adds a new item
Serbian Hound
he wants to update it just locally?
so it's like adding multiple items and save them at once
Serbian Hound
ah yeah batching them
sorry didnt see that bit
then yeah you'd wanna have that part in client component
Philippine CrocodileOP
initially, render on the server, and then update locally. batching updates
you got the point @Philippine Crocodile
Don't forget to revalidate the cache btw
Mark solution if anything helped you 🙂
Serbian Hound
james u noob
@Serbian Hound james u noob
please be respectful.