Handle client-side and server-side at the same time
Answered
Bigheaded ant posted this in #help-forum
Bigheaded antOP
Hello everyone, can anyone give me a clue about how I can solve this problem? I have a case where I want to create a splash screen effect using session storage to identify whether the user has already visited the website or not. However, when I use useEffect, Next.js tells me it's client-side, which isn't supported if I'm using metadata for the title. So, what's the best way to solve this?
// app/layout.tsx
/* eslint-disable @typescript-eslint/no-explicit-any */
"use client"; // Enable client-side features
import { Montserrat } from "next/font/google";
import "./globals.css";
import SplashScreen from "@/components/partials/splash-screen";
import { generatePageMetadata } from "@/utils/get-page-metadata";
import { useEffect, useState } from "react";
const montSerrat = Montserrat({
subsets: ["latin"],
});
// Dynamic metadata handler
export async function generateMetadata({
params,
}: {
params: any
}) {
return generatePageMetadata({ slug: params.slug || "index" });
}
// export const metadata: Metadata = {
// title: "Create Next App",
// description: "Generated by create next app",
// };
export default function RootLayout({
children,
}: Readonly<{
children: React.ReactNode;
}>) {
const [showSplash, setShowSplash] = useState(true);
useEffect(() => {
const splashShown = sessionStorage.getItem("splashShown")
if(splashShown) setShowSplash(false);
else {
sessionStorage.setItem("splashShown", "true");
setTimeout(() => setShowSplash(false), 2000)
}
}, [])
if (showSplash) {
return (
<html lang="en">
<body className={`${montSerrat.className} antialiased`}>
<SplashScreen />
</body>
</html>
);
}
return (
<html lang="en">
<body
className={`${montSerrat.className} antialiased`}
>
{children}
</body>
</html>
);
}Answered by Luis
Split your components:
- The Layout remains a server componen which means you get to use the metadata API, and the other cools feature from RSC
- move the component that needs useState and useEffect to a different file with “use client” at the very top, this will make it a client component.
- The Layout remains a server componen which means you get to use the metadata API, and the other cools feature from RSC
- move the component that needs useState and useEffect to a different file with “use client” at the very top, this will make it a client component.
4 Replies
Split your components:
- The Layout remains a server componen which means you get to use the metadata API, and the other cools feature from RSC
- move the component that needs useState and useEffect to a different file with “use client” at the very top, this will make it a client component.
- The Layout remains a server componen which means you get to use the metadata API, and the other cools feature from RSC
- move the component that needs useState and useEffect to a different file with “use client” at the very top, this will make it a client component.
Answer
If you want to conditionally render either the splash thing or children (which I don’t get why but whatever) you can pass children to <SplashComponent> and inside of it render one or the other conditionally
@Luis Split your components:
- The Layout remains a server componen which means you get to use the metadata API, and the other cools feature from RSC
- move the component that needs useState and useEffect to a different file with “use client” at the very top, this will make it a client component.
Bigheaded antOP
Oh so I just need to move the useState and useEffect to a client component, and put the component on the layout.
Yes, that’s the way of doing things now since components are server components by default