skip to Main Content

I have a theme switch toggle on the top AppBar which is a client component.

enter image description here

The main layout is SSR and uses the nextjs App router. It has theme settings <ThemeProvider theme={lightOrDarkTheme}>. Prior to App router/SSR I was able to use the cookie I set in the TopAppBar component to affect the theme change in layout file. With SSR, the cookie which is set and I can see in the browser is not accessible by server. Cookie is on the client side, the layout.jsx file cannot read the cookie and hence the theme toggle does not work.

enter image description here

I would appreciate tips on how to achieve this.

  • I do not want to ‘use client’ at a top level such as layout.jsx as it defeats the purpose of SSR.
  • I also do not want to change TopAppBar to use server as it has way too much client code such as useEffect, mui styles …

Here is layout.jsx

import {lightTheme, darkTheme} from '@/components/theme';
import TopAppBar from '@/components/ui/topAppBar';
import { cookies } from 'next/headers';
const cookieStore = cookies();

export default function RootLayout({
    children,
  }) {
    
    const cookieDark = cookieStore.get('darkTheme').value;
    const theme = cookieDark=="true"? darkTheme: lightTheme;
    ....
   <ThemeProvider theme={theme}>

And here is TopAppBar code:

'use client'
...
export default function TopAppBar() {
...
  const handleThemeChange = () => {
    setCookie('darkTheme',cookies.darkTheme == "true"? false: true, { path: '/' });
    setDarkState(cookies.darkTheme == "true"? false: true);
  };

Edit: Adding screenshot showing that cookie value is always false on cookies from next/header. Left: Browser (Client) and Right (Server console)
enter image description here

2

Answers


  1. Chosen as BEST ANSWER

    Hope this will be useful for someone else. Seems to be a bug in nextJs?

    This strangely does not work (This is the way shown the next js docs)

    import { cookies } from 'next/headers';
    const cookieStore = cookies();
    
        export default function RootLayout({
          ...
            
            const cookieDark = cookieStore.get('darkTheme'); //This does not synch when cookies on browser changes
    

    However, if you directly use cookies.get(), it works

    import { cookies } from 'next/headers';
    
    export default function RootLayout({
       ...
        const cookieDark = cookies().get('darkTheme'); //This synchs when cookies on browser changes
    

  2. the layout.jsx file cannot read the cookie and hence the theme toggle
    does not work.

    you can.

    you can access cookies from server side, nextJs have a function for this.

    reference : https://nextjs.org/docs/app/api-reference/functions/cookies.

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