skip to Main Content

I have a Next app. I use app folder and Next Auth library. So that each page has access to the session, I wrapped the entire application in a SessionProvider. But since it’s useContext under the hood, I had to add the 'use client' directive everywhere. This resulted in all pages being client-side since they use useSession. And all page components (buttons, inputs) also became client-side.

app/layout.tsx

const RootLayout = ({ session, children }: { session: Session; children: ReactNode }) => {
    return (
        <SessionProvider session={session}>
                <html lang={`eng`} 
                    <head>
                    </head>
                    <body>
                        {children}
                    </body>
                </html>
        </SessionProvider>
    )
}

some protected page

'use client';

import {useSession} from "next-auth/react";

export default function ProtectedPage() {
    const {data, status} = useSession()


    return (
                <div>
                    {status === "authenticated" ? <div>data.name</div> : null}
                </div>
    )
}

Is it normal that all pages and components are now rendered on the client? The Next Auth documentation recommends wrapping everything in a provider, but then the main feature of Next.js, namely SSR, no longer works

2

Answers


  1. No, not every component needs to be a client component. You could create a wrapper component that is a client component which receives children. Both server and client components can be passed to client components as children.

    Example wrapper component
    "use client";
    
    import NoAuthComponent from "components/NoAuthComponent";
    
    interface Props extends React.PropsWithChildren {}
    
    // if the no auth view was provided as a prop rather then
    // imported you could also make it a server component
    export default function ProtectedView({ children }: Props): JSX.Element {
      const session = useSession();
      if (session?.status !== "authenticated") return <NoAuthComponent />;
      return <>{children}</>;
    }
    
    Example usage
    import "server-only";
    
    import ProtectedView from "components/ProtectedView";
    import MyServerComponent from "components/MyServerComponent";
    
    export default async function MyPage(): Promise<JSX.Element> {
      const response = await fetch("...");
      const data = await response.json();
      return (
        <ProtectedView>
          <MyServerComponent data={data} />
        </ProtectedView>
      );
    }
    

    More information about composing, nesting and working with client and server components can be found inside the official documentation.

    Login or Signup to reply.
  2. Is it normal that all components in Next.js are client components?

    Every component under the app folder is, by default, a server component, meaning that it’s rendered on the server side, and its code stays on the server side.

    With use client

    Is it normal that all pages and components are now rendered on the client?

    You can mix server component in client component as its children.

    <ClientComponent>
      <ServerComponent />
    </ClientComponent>
    

    For further detail, read this article on dev.to.

    You may also be interested to read this blog on medium.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search