skip to Main Content

I’m encountering a hydration error in a Next.js project when using the Shadcn Dialog component. The error message is:

"Hydration failed because the initial UI does not match what was rendered on the server."

Here are the key components:

modal.tsx:

// Importing Dialog components from Shadcn
import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle } from "@/components/ui/dialog";

interface ModalProps {
  title: string;
  description: string;
  isOpen: boolean;
  onClose: () => void;
  children?: React.ReactNode;
}

export const Modal: React.FC<ModalProps> = ({
  title,
  description,
  isOpen,
  onClose,
  children
}) => {
  const onChange = (open: boolean) => {
    if (!open) {
      onClose();
    }
  };

  return ( 
    <Dialog open={isOpen} onOpenChange={onChange}>
      <DialogContent>
        <DialogHeader>
          <DialogTitle>{title}</DialogTitle>
          <DialogDescription>
            {description}
          </DialogDescription>
        </DialogHeader>
        <div>
          {children}
        </div>
      </DialogContent>
    </Dialog>
  );
};


import { Modal } from "@/components/ui/modal";

const SetupPage = () => {
  return (
    <div className="p-4" suppressHydrationWarning={true}>
      <Modal title="Test" description="Test Desc" isOpen onClose={() => {}}>
        Children
      </Modal>
    </div>
  );
}

export default SetupPage;

I’ve included the relevant code snippets, and the issue arises during hydration. Any insights or solutions would be greatly appreciated. Thanks!

Attempted to use Shadcn’s Dialog component in a Next.js project. Expected smooth rendering, but encountered a hydration error:

2

Answers


  1. I ran into the same error as you did. Hydration error often occurs when you are dealing with modal pop-ups, caused by the mismatching of the rendering result between the server side and the client side.

    One workaround is to add a checking logic to ensure your Dialog is only rendered on the client side:

      const [isMounted, setIsMounted] = useState(false);
    
      useEffect(() => {
        setIsMounted(true);
      }, []);
    
      if (!isMounted) {
        return null;
      }
    
      return <YourDialogComponent/>  // only on client side
    

    I believe you are trying to build an e-commerce website watching Code With Antonio since your source code exactly matched the content of his tutorial (and I am doing the same thing haha) (forgive me if I am wrong).
    And he did the same thing as described above in his tutorial afterwards so you won’t get this error after a while if you keep following.

    Cheers!

    See also:

    https://nextjs.org/docs/messages/react-hydration-error

    https://github.com/radix-ui/primitives/issues/1386

    How to solve react hydration error in Nextjs

    Login or Signup to reply.
  2. Ive been using dynamic imports with ssr set to false as a workaround for several shadcn components. I also think modals should be dynamic in general.
    Eg:

    const Modal = dynamic(()=>import("./pathToFile/Modal"), {ssr: false, loading: ()=> <AnyPlaceHolder />})
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search