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.