Is it normal that all components in Next.js are client components?
Asked Answered
A

2

6

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

Axolotl answered 12/6, 2023 at 9:40 Comment(0)
O
3

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.

Orenorenburg answered 12/6, 2023 at 15:4 Comment(0)
F
2

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.

Firedrake answered 12/6, 2023 at 14:39 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.