Next.js Discord

Discord Forum

Handle client-side and server-side at the same time

Answered
Bigheaded ant posted this in #help-forum
Open in Discord
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.
View full answer

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.
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
Yes, that’s the way of doing things now since components are server components by default