Can server components be changed in the client?
Answered
Atlantic mackerel posted this in #help-forum
Atlantic mackerelOP
I'm building a realtime chat application using Nextjs. I want the server component(chat history) be dynamically rendered on page load, then the following messages should be appended to the chat history by WebSocket or DOM events. Is there any way to implement that without changing it to a client component or refetching/revalidating its path? I'm aware that WebSocket can only be in client components. But I'm new to Nextjs so I'm making sure in case there is a way.
Answered by joulev
Fetch initial data in server component, then pass that data as prop to a client component. In that client component, store the data as a react state and render the list based on that state. Update the state with new data in the client side ws handling.
21 Replies
I'm not sure if a completely SSR method is there but it will probably be a headache to implement even if it was there
Using the client for the actual message frame would work best if you want to use websocket
Also if you are deploying to a serverless platform, use things like ably or pusher instead
@Atlantic mackerel I'm building a realtime chat application using Nextjs. I want the server component(chat history) be dynamically rendered on page load, then the following messages should be appended to the chat history by WebSocket or DOM events. Is there any way to implement that without changing it to a client component or refetching/revalidating its path? I'm aware that WebSocket can only be in client components. But I'm new to Nextjs so I'm making sure in case there is a way.
West African Lion
i actually did something like this before by creating a client component, that renders that server component with a useEffect hook
@Clown I'm not sure if a completely SSR method is there but it will probably be a headache to implement even if it was there
Atlantic mackerelOP
Thanks for the input👍 My APIs are implemented in a separate backend server which aren't accessible to the clients. And making route handlers would add up the complexity. So I think data fethcing should only be done in Nextjs.
@West African Lion i actually did something like this before by creating a client component, that renders that server component with a useEffect hook
Atlantic mackerelOP
How did you do? could you elaborate
@Atlantic mackerel How did you do? could you elaborate
West African Lion
i exported the server components from a file, then i imported them in a new file with use client, i recreated those components with useEffect then i imported it again to my main client component so the tree was like
from server to client with useeffect to client before it could actually update in real time
from server to client with useeffect to client before it could actually update in real time
Atlantic mackerelOP
Doesn't that turn the server components into client components?
@West African Lion i exported the server components from a file, then i imported them in a new file with use client, i recreated those components with useEffect then i imported it again to my main client component so the tree was like
from server to client with useeffect to client before it could actually update in real time
Atlantic mackerelOP
I don't see the picture😅 Can you share a simple code example?
@Atlantic mackerel I don't see the picture😅 Can you share a simple code example?
West African Lion
yh ok wait i'm coming
Server component example:
First client component with useEffect hook:
Then final destination:
export async function fetchByMain(ing : string) {
const response = await fetch(`https://www.themealdb.com/api/json/v1/1/filter.php?i=${ing}`, {cache: 'no-store'});
const data = await response.json();
if (data.meals == null){
return (
<NoMeal term={`${ing}`} />
)
}
return data.meals.map((item:MealProp,index:number) =>{
return (
<MainIngResult text={item} key={index} />
)
});
}First client component with useEffect hook:
export function IngredientResult({term}:{term:string}){
const [ results, setResults ] = useState<any>();
useEffect(() => {
const result = fetchByMain(term)
setResults(result)
},[ term ])
return results
}Then final destination:
function Result({ val,term }:{term:string, val:string}){
let resultComponent;
if (val !=="ingredient" && term === "") {
resultComponent = <></>;
}else if (val === 'country') {
resultComponent = <AreaResult term={term} />;
} else if (val === 'categories') {
resultComponent = <CategoryResult term={term} />;
} else if (val === 'ingredient') {
resultComponent = <IngredientResult term={term} />;
} else if (val === 'name') {
// Handle 'name' case if needed
resultComponent = <DetailedRecipeName term={term} />
}
return resultComponent;
}so here it changes when client changes also
Atlantic mackerelOP
@West African Lion I tried the code but the fetching is actually done in the browser. Is fetching in your app done in the browser or server?
@Atlantic mackerel I'm building a realtime chat application using Nextjs. I want the server component(chat history) be dynamically rendered on page load, then the following messages should be appended to the chat history by WebSocket or DOM events. Is there any way to implement that without changing it to a client component or refetching/revalidating its path? I'm aware that WebSocket can only be in client components. But I'm new to Nextjs so I'm making sure in case there is a way.
Fetch initial data in server component, then pass that data as prop to a client component. In that client component, store the data as a react state and render the list based on that state. Update the state with new data in the client side ws handling.
Answer
Atlantic mackerelOP
wait a sec
Atlantic mackerelOP
@joulev HOLY SHIIIIIIIT YOU SAVE ME AGAIN
THANKS A LOT SENPAI @joulev 

You’re welcome
Atlantic mackerelOP
yeah I think if you import a server component in a client component, Next will automatically turn it to a client component.