Rendering message on React Server Component page load
ScreamZ opened this issue · comments
I would like your insight on a use case,
I'm using NextJS with RSC and I would like to display a message to a user arriving on the website only if it is logged.
Currently I ended up with this pattern, but sadly I have to render null, is there any way to proceed ? I used such pattern when hooks where not existing, but now we are supposed to use hooks, but using a custom hook with use client
doesn't seems to work.
"use client";
import { Session } from "next-auth";
import { useEffect, useRef } from "react";
import { toast } from "sonner";
type HelloBannerProps = {
session: Session | null;
};
export function HelloBanner({ session }: HelloBannerProps) {
const isHandled = useRef(false);
useEffect(() => {
const userName = session?.user?.name;
if (userName && !isHandled.current) {
isHandled.current = true;
requestAnimationFrame(() => toast(`Welcome back to the ${userName}!`));
}
}, [session]);
return null;
}
Thanks
EDIT:
Humm, it seems complicated with server components when the URL change useEffect
is played again. Not sure how to deal with my use case now
I guess this is a use case for a full client mode? But how? Was easier with page router 😅
Screen.Recording.2024-05-01.at.18.52.02.mov
Hi @ScreamZ,
You can extract out the part the needs to rendered on the client side only to a separate component and import the component into the server component using a dynamic import.
Example: (Javascript)
// ServerComponent.js
// Importing the component using 'next/dynamic' so that its only be rendered on the client side, not server side.
const ClientComponet = dynamic(() => import("./ClientComponent.js"), {
ssr: false // When setting the SSR flag to false, the component is not pre-rendered on the server.
})
export default function ServerComponent() {
return (
// Application code.
<ClientComponent />
)
}
For more details you can read the official docs on the NextJs Website (next/dynamic)
Yes thanks, but doing this way I still need to render an empty component, i cannot just use an hook isn't ?
I am also creating a toast library (toast-ease@v0.0.1), you can have a look at that, though its still under development. (https://github.com/gurvirsinghbaraich/toast-ease)
@ScreamZ Hi, I also published the package to npm registry (https://www.npmjs.com/package/toast-ease). The project is still at v0.0.1. The package supports rendering a toast from client side and server side.
Video Demo
demo.mov
Code
// Layout.tsx
import { ToastBox } from "toast-ease";
import { ServerToastRegister } from "toast-ease/server";
export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
return (
<html lang="en">
<body className={spaceGrotesk.className}>
<ServerToastRegister />
<ToastBox duration={3} toastsVisible={5} />
<main>{children}</main>
</body>
</html>
);
}
Rendering a toast from server is this simple
// page.tsx
import { toast } from "toast-ease/server";
export default async function Homepage() {
toast({
// An env variable that is only available on the server
title: process.env.SERVER_SECRET,
});
return (
null
);
}