NextJS Hydration Error beacuse of `useMediaQuery` usage

I have a dynamic page like this in nextjs:

/* Imports */

async function getData(id: string) {
  const res = await fetch(`${process.env.NEXT_PUBLIC_API_URL}/homework/${id}`, {
    cache: 'no-cache',
  });

  if (!res.ok) {
    throw new Error('Failed to fetch data');
  }

  return (await res.json()) as Homework;
}

export default async function HomeworkPage({
  params,
}: {
  params: { name: string };
}) {
  const data = await getData(params.name);

  return (
    <>
   /* Some client and server components */
    </>
  );
}

This page is rendered using this layout:

'use client';

import { AnnouncementBar } from '@/components/editor/components/announcement-bar';
import { Footer } from '@/components/footer';
import { HeaderApp } from '@/components/header-app';
import { QuickBar } from '@/components/ui/quick-bar';

interface AppLayoutProps {
  children: React.ReactNode;
}

export default function AppLayout({ children }: AppLayoutProps) {
  return (
    <div className='flex min-h-screen flex-col'>
      <AnnouncementBar />
      <HeaderApp />

      <main className='flex flex-1 pt-[calc(var(--announcement-bar-height)+var(--header-height))]'>
        <div className='container px-3 py-6 md:px-6'>{children}</div>
        <QuickBar />
      </main>

      <Footer />
    </div>
  );
}

Where for example in AnnounementBar I have the following logic that uses both lcoalStorage in getUserOrGuest method and useMediaQuery in useIsDesktop:

"use client"

export const AnnouncementBar = () => {
  const user = getUserOrGuest();
  const isDesktop = useIsDesktop();

  return (
    <div
      className={clsx(
        'z-[50] h-[40px] w-full border-y-[1px] border-border/90 scrolled:h-0',
        'flex items-center justify-center text-sm transition-[opacity,height] duration-200',
        'overflow-hidden scrolled:border-none scrolled:leading-[0] scrolled:opacity-0',
        'fixed left-0 top-0 bg-header p-2'
      )}
    >
      <div className='flex items-center gap-1.5'>
        <AlertTriangle className='mr-2' />
        {isDesktop && <span>Platforma jest w wersji</span>}

        <ResponsiveDialog
          trigger={
            <Button
              variant='ghost'
              className='hover:bg-initial m-0 flex gap-1 p-0 text-violet-11 hover:text-violet-12 hover:underline'
            >
              <span className='font-bold'>
                {isDesktop ? 'testowej!' : 'wersja testowa!'}
              </span>
            </Button>
          }
          title='Wersja testowa'
          content={
            <div className='flex flex-col gap-3'>
              <p>
                Ponieważ jesteśmy nowo powstałą platformą, potrzebujemy czasu
                aby przetestować wszystkie funkcjonalności oraz uzupełnić
                platformę o wartościowe treści. Do tego czasu{' '}
                <span className='font-bold text-red-10 underline underline-offset-4'>
                  rejestracja kont ucznia jest wyłączona!
                </span>
              </p>
              <p className='font-bold'>
                Jesteś nauczycielem?{' '}
                <Link className='mw-link' href='/register/teacher'>
                  Dołącz do nas!
                </Link>
              </p>
            </div>
          }
        />
      </div>
      {user && (
        <Link
          className='ml-5 whitespace-nowrap font-bold text-red-10 hover:text-red-11'
          href='/feedback'
        >
          Zgłoś błąd lub sugestię
        </Link>
      )}
    </div>
  );
};

The problem is that for some reason this component is server side rendered and then I have a hydration error because when I reload page, initially the mobile view is rendered and user is null and then it is replaced by the proper view (user is taken from localStorage and isDesktop is false). I don’t really get why is that a case. Any ideas?