Problems with Server Components/Client Components

I'm sorry if my title isn't too descriptive. I've been struggling with this problem for two days and might go crazy soon.

In my application, i fetch data with my Header client from prismic, which is server-sided of course, and then I want to pass it on to the HeaderClient component for the mobile navbar toggling and whatnot. But whenever I do that I get this error:

Error: async/await is not yet supported in Client Components, only Server Components. This error is often caused by accidentally adding 'use client' to a module that was originally written for the server.

My Header component looks like this:

import { createClient } from '@/prismicio';
import HeaderClient from './clientsided/header/HeaderClient';
import styles from './Header.module.css';

export async function Header() {
  const client = createClient();
  const navbar = await client.getSingle('navbar');

  return (
    <section className={styles.HeaderContainer}>
      <HeaderClient navbar={navbar} styles={styles} />
    </section>
  );
}

My HeaderClient component looks like this:

'use client';

import React, { useState, useEffect } from 'react';
import HeaderMobile from './HeaderMobile';
import HeaderDesktop from './HeaderDesktop';

const HeaderClient = function ({
  navbar,
  styles,
}: {
  navbar: any;
  styles: any;
}) {
  const [windowWidth, setWindowWidth] = useState<number | null>(null);

  useEffect(() => {
    const handleResize = () => {
      setWindowWidth(window.innerWidth);
    };

    handleResize();

    window.addEventListener('resize', handleResize);

    return () => window.removeEventListener('resize', handleResize);
  }, []);

  return (
    <header className={styles.Main}>
      {windowWidth !== null && windowWidth <= 768 ? (
        <HeaderMobile navbar={navbar} styles={styles} />
      ) : (
        <HeaderDesktop navbar={navbar} styles={styles} />
      )}
    </header>
  );
};

export default HeaderClient;



and my HeaderMobile looks like this:

'use client';

import React, { useState, useEffect, Suspense } from 'react';
import { PrismicNextLink } from '@prismicio/next';
import { usePathname } from 'next/navigation';
import { Logo } from '@/components/Logo';

const HeaderMobile = ({ navbar, styles }: { navbar: any; styles: any }) => {
  const pathname = usePathname();
  const [isActive, setIsActive] = useState('');
  const [isOpen, setIsOpen] = useState(false);

  const toggleOpen = () => {
    isOpen ? setIsOpen(false) : setIsOpen(true);
  };

  return (
    <section className={styles.Main}>
      <Logo logo={navbar.data.logo} />
      <section
        className={`${styles.NavbarMobile} ${isOpen ? styles.IsOpen : ''}`}
      >
        <div className={styles.NavListMobileContainer}>
          <ul className={styles.NavListMobile}>
            <li
              key="/"
              className={`${styles.Item} ${isActive ? styles.isActive : ''}`}
            >
              <p>01</p>
              <a href="/" className={styles.Link}>
                Home
              </a>
            </li>
            {navbar.data.navbar.map(
              (
                {
                  link,
                  label,
                  identifier,
                }: { link: any; label: string; identifier: string },
                index: number
              ) => (
                <li key={identifier} className={styles.Item}>
                  <p>{(index + 2).toString().padStart(2, '0')}</p>
                  <PrismicNextLink field={link} className={styles.Link}>
                    {label}
                  </PrismicNextLink>
                </li>
              )
            )}
            <div className={styles.LogoContainerMobile}>

          </ul>
        </div>
      </section>
      <div className={styles.HamburgerContainer} onClick={toggleOpen}>
        <button className={styles.Hamburger}>
          <span className={styles.HamburgerLine}></span>
          <span className={styles.HamburgerLine}></span>
          <span className={styles.HamburgerLine}></span>
        </button>
      </div>
    </section>
  );
};

export default HeaderMobile;

If I comment out both the HeaderMobile and HeaderDesktop components it "works", or at least I don't get the error. If I use a Suspense boundary i don't get the error but the HeaderClient gets remounted every time i click on the hamburger, so also not the solution. I use the same approach in many other components (Footer, App.tsx in the root folder etc.) and there it works, but not in the Header. I would really appreciate it if someone had an answer to this and could help me I'd like to keep my hair.

I found the reason. If anyone will run into the same problem, which I doubt, I rendered the Logo component on the server and this, of course, didn't work. I've replaced it with PrismicNextImage and now it works just fine:)

2 Likes