0

This question is related to my two previous questions on the subject :

So, my objective is to have a Context API and different layouts based on auth state in a SEO friendly manner.

Now I have the following code :

My folder structure

/app
--Layouts
  --Auth.jsx
  --Main.jsx
--layout.jsx
--Context.jsx
--page.jsx

./layout.jsx

import AppWrapper from './Context.jsx';

export default function RootLayout({ children }) {
    return (
        <html lang="fr">
        <body>
            <AppWrapper>
                {children}
            </AppWrapper>
        </body>
        </html>
    )
}

./Context.jsx

"use client";
import { createContext, useContext, useState} from 'react';
import Main from "./Layouts/Main.jsx";
import Auth from "./Layouts/Auth.jsx";

const Context = createContext();

export default function AppWrapper({children}) {
    const [isAuth, setAuth] = useState(false)
    return (
        <Context.Provider value={{
            isAuth: isAuth,
            setAuth: setAuth
        }}>
            {   !isAuth ?
                <Main>{children}</Main>
                :
                <Auth>{children}</Auth>
            }
        </Context.Provider>
    )
}

export function useAppContext() {
    return useContext(Context);
}

./Layouts/Main.jsx (Same for Layouts/Auth.jsx)

export default function Main({ children }) {
    console.log('children of main');
    return (
        <>
        <p>Im main</p>
        {children}
        </>
    )
}

./page.jsx

'use client'
import { useAppContext } from './Context';
import Context from "./Context";

export default function Home() {
    const context = useAppContext(Context);
    return (
        <>
        <p>Im self</p>
        <button onClick={() => context.setAuth(current => !current)}>Toggle</button>
        </>
    )
}

As you can see :

  • root layout is a server component
  • ./Context.jsx is a client component
  • ./Layouts are server components
  • ./page.jsx is a client component

But the console.log in ./Layouts/Main.jsx is displayed on the browser console.

So :

  • Is it a client component ?
  • Does this makes the whole app client side rendered ?
  • How to optimize all of that ?
  • What am I missing ?
Jonas
  • 121,568
  • 97
  • 310
  • 388
JeanJacquesGourdin
  • 1,496
  • 5
  • 25
  • You have rendred `Main` directly inside `AppWrapper` which is a client component, so yeah, it's a client component. Only a component passed as part of `props` to a client component can be a server component. See https://nextjs.org/docs/getting-started/react-essentials#nesting-server-components-inside-client-components. – Youssouf Oumar May 20 '23 at 09:19
  • @YoussoufOumar So what i'm trying to do is basically impossible ? And i'm not speaking about using native nextjs layouts... I'll have to create separate urls for auth and not authed... – JeanJacquesGourdin May 20 '23 at 09:44
  • I would say you are worrying too much. When using Next.js, even client components are rendered on the server and hydrated on the client, whereas server components won't be hydrated. The difference between the two here resides in the amount of JavaScript sent to the browser for the hydration. See https://nextjs.org/docs/app/building-your-application/rendering for more. – Youssouf Oumar May 20 '23 at 09:48
  • @YoussoufOumar I'm not sure. If i go for what i showed here, all the app is going to be client side rendered, making it whole not SEO friendly. I can simply not accept that – JeanJacquesGourdin May 20 '23 at 10:01

1 Answers1

0
  • Is it a client component ?

Yes

  • Does this makes the whole app client side rendered ?

Yes

  • How to optimize all of that ?

Keep the auth state on server using cookies, display and revalidate layouts on server for each user.

  • What am I missing ?

Need to forget SPA architecture, Context API is nice but outdated when it comes to conditionally render meta-components/layouts. Its place is at root only passing children and used only on leaf components.

JeanJacquesGourdin
  • 1,496
  • 5
  • 25