Next.js Discord

Discord Forum

Hydration error caused by shadcn-ui sheet component

Answered
British Shorthair posted this in #help-forum
Open in Discord
British ShorthairOP
"use client";
import { useMediaQuery } from "react-responsive";
import CommandMenu from "./CommandMenu";
import { logo } from "./util";
import { Sheet, SheetContent, SheetTrigger } from "../ui/sheet";

export default function Sidebar() {
  const isTabletOrMobile = useMediaQuery({ query: "(max-width: 768px)" });

  if (isTabletOrMobile)
    return (
      <Sheet>
        <SheetTrigger asChild>
          <button className="absolute bottom-10 left-10">Open</button> <-- this is causing error
        </SheetTrigger>
        <SheetContent className="w-1/2" side="left">
          <div>
            <h1 className="p-2 text-lg font-semibold text-center">
              <a href="/" className="text-black">
                {logo}
              </a>
            </h1>
            <CommandMenu />
          </div>
        </SheetContent>
      </Sheet>
    );

  return (
    <div className="border-r w-52 bg-white mobile:-ml-52 transition-all">
      <h1 className="p-2 text-lg font-semibold text-center">
        <a href="/" className="text-black">
          {logo}
        </a>
      </h1>
      <CommandMenu />
    </div>
  );
}


I expected this component will be rendered on the client side because of use client directive.
but it says server render result and client render result are different.
<button> is added on the client side rendering.
Answered by Arinji
you dont ask to get rendered on the client only
View full answer

136 Replies

British ShorthairOP
'use client';
export default function Sidebar() {
  const isTabletOrMobile = useMediaQuery({ query: "(max-width: 768px)" });
  const [isMounted, setIsMounted] = useState(false);

  useEffect(() => {
    setIsMounted(true);
  }, []);

  // isMounted
  if (isTabletOrMobile && isMounted)
    return (
      <Sheet>
        <SheetTrigger asChild>
          <button className="absolute bottom-10 left-10">Open</button>
        </SheetTrigger>
        <SheetContent className="w-1/2" side="left">
          <div>
            <h1 className="p-2 text-lg font-semibold text-center">
              <a href="/" className="text-black">
                {logo}
              </a>
            </h1>
            <CommandMenu />
          </div>
        </SheetContent>
      </Sheet>
    );

  return (
    <div className="border-r w-52 bg-white mobile:-ml-52 transition-all">
      <h1 className="p-2 text-lg font-semibold text-center">
        <a href="/" className="text-black">
          {logo}
        </a>
      </h1>
      <CommandMenu />
    </div>
  );
}

But this solved the error.
and I do not understand the reason why use client directive could not solve the issue.
You can see I added isMounted state and update the value to true after rendering on the client side.
@British Shorthair
in your initial issue
useEffect(() => {
    setIsMounted(true);
  }, []);


you were on the right track, but i dont see where you used this lol
just curious
British ShorthairOP
ah no it's mistake
you can ignore that useEffect there
ok so now for your actual issue
British ShorthairOP
I fixed the code thanks
use client components are rendered on the server and the client
British ShorthairOP
whattt?
yea :D
use client isnt actually client components
British ShorthairOP
that's a shocking story now..
think of it like this
when you add use client, you tell nextjs that you want access to client api's
British ShorthairOP
then.. a lot of docs are shit out there eh..
@British Shorthair then.. a lot of docs are shit out there eh..
dont see external stuff
they are usually wrong
British ShorthairOP
damnit...
just go thru the nextjs docs, and this discord
First it renders on the server even though it's a client components
^^
British ShorthairOP
i am still confused..
so in your initial issue, on the server it got a diff result
@Arinji so in your initial issue, on the server it got a diff result
and on the client it got a diff issue
this leads to another react thing called hydration
Client side html and server side html doesn't match basically
where it tries and links the server stuff to the client stuff
if it dosent match, it will throw a hydration error.. which you faced
now the easiest fix to this, is just put yoour client computations in a useEffect
this is because, nextjs when its server rendering will just skip the useEffect
and for checking if you are on client mode or server mode, you do the mounted thing as you did in the useEffect
if the flag state is true, that means your on client mode
makes sense? @British Shorthair
its a pretty complicated thing so feel free to ask if you are confused
Yeah the next14 hydration error messages are also not very much guiding
I've heard they'll make it better in next15 ig
they will show differences between server and client results
stuff like Server Got: 12
Client got: 15
type thing
Oh finally when I first started next it was so difficult to get my head around this and know where it was different
British ShorthairOP
but the error is talking about "button" component
Specially when working with dates
British ShorthairOP
and i can see that Sidebar component was rendered on the server side even tho there's use client directive
Is it correct?
and button was rendered on the client side
its rendered once on the server
hence client components have the same performance as server components
British ShorthairOP
but that's so wrong that is called "Client component" if it's also rendered on the server eh?
I kinda get the idea now but not clear still
Server side rendering doesn't mean just server components my guy
British ShorthairOP
huh?
@British Shorthair but that's so wrong that is called "Client component" if it's also rendered on the server eh?
its considered a client component, cause it hooks into the client api.. but yes the naming is shit
everyone gets confused with it
British ShorthairOP
oh
heard of use server?
British ShorthairOP
that makes sense now..
thats for making server actions :D
British ShorthairOP
yes
use server is the default
its just bad naming
British ShorthairOP
what?
"use c"
British ShorthairOP
no
@British Shorthair what?
make a diff forum for that lol
Printf("next naming is shit");
i was tryna explain how naming is just shit here
British ShorthairOP
ah
makes sense
yea :D
British ShorthairOP
so you mean use client is not about rendering on the client side
it's not about rendering it's about what..?
also i am cnofused with client api thingy. I never heard of this too.
More like client side interactivity
@British Shorthair also i am cnofused with `client api` thingy. I never heard of this too.
useState, useEffect.. basically react hooks are considered client apis
use client makes it so you tell the nextjs compiler
British ShorthairOP
that makes sense now
i want to use those
so instead of you telling the nextjs compiler "render this only only on the client" you say "i want to use react hooks and other client interactions, so hydrate me once on the client as well please"
Also event handlers like on clicks and so on whatever you need the browser client side interactivity
^^
British ShorthairOP
ok now it's getting clearer imo
dw, will take a while :D
British ShorthairOP
so my understanding is that use client does not mean render this component on the only client side but it's about hydrating the client api code.
you dont ask to get rendered on the client only
Answer
you ask to get rendered on the client once at the end
server rendering is always
British ShorthairOP
return (
    <div className="border-r w-52 bg-white mobile:-ml-52 transition-all">
      <h1 className="p-2 text-lg font-semibold text-center">
        <a href="/" className="text-black">
          {logo}
        </a>
      </h1>
      <CommandMenu />
    </div>

so this code will be rendered on the server even tho the file has use client directive on the top, right?
yes.
British ShorthairOP
how can you read my msg so fast
u are ai
nah lmao
everything is always rendered on the server once
so i just saw the first 5 words
said yes while reading the rest
when your grinding help forums, you gotta be fast lol
@Arinji everything is always rendered on the server once
British ShorthairOP
This is insane tbh... because folks i have talked with, to study Next.JS together they and I had knew use client renders it only client side
wtf
British ShorthairOP
so if I really want to render it only on client side then I have to use this.
  useEffect(() => {
    setIsMounted(true);
  }, []);

  // isMounted
  if (isTabletOrMobile && isMounted)
isMounted
Yes
British ShorthairOP
wow now makes sense
everything is so clear
np :D
any other confusion?
@Arinji dont hang around with those folks lol
British ShorthairOP
my man some are my friends too
your only friend is nextjs
I need help with implementing a multi role access control in a CMS
:meow_stare:
British ShorthairOP
but how they become function on the client side tho? i mean useEffect and stuff
Long-legged ant
:blob_aww:
British ShorthairOP
how Next.JS send this useEffect to the client side?
Compiler is smart enough to know
British ShorthairOP
in object format?
wait.. I remember the term "RSC"
Long-legged ant
react server compoent
British ShorthairOP
i heard they use special object format for those hydration thingy
@British Shorthair wait.. I remember the term "RSC"
React Server Components
British ShorthairOP
it was RSC Json ?
idk
British ShorthairOP
RSC Payload
I've made a forum
British ShorthairOP
yes this
this was the something I was talking about
useEffect is included inside RSC Payload
as I know
btw mark a solution @British Shorthair
Original message was deleted
boop