Next.js Discord

Discord Forum

Modal - document is not defined error in Console

Answered
Asiatic Lion posted this in #help-forum
Open in Discord
Asiatic LionOP
I'm trying to create a modal component but I'm stuck on "document is not defined" error in console. Any ideas?

''use client";
import { createPortal } from "react-dom";

interface ModalProps {
open: boolean;
}

const Modal = ({ open }: ModalProps) => {
return (
open &&
createPortal(
#Unknown Channel
<div className="modal-dialog">
<h1>Modal</h1>
</div>
<div className="modal-backdrop"></div>
</>,
document.body
)
);
};

export default function Home() {
return <Modal open={true} />;
}
Answered by Ray
if you create modal in this way, you gotta disable SSR for this component with dynamic import like this
const Modal = dynamic(() => import('./modal'), { ssr: false })
View full answer

3 Replies

Answer
Asian black bear
We were facing this issue in the project I'm working on (MDB React Ui Kit). The error appears, because browser-specific objects are not defined on the server. We've created a wrapper-component which solves this issue, and we're going to add it in next release.

Use this workaround to solve this kind of errors for any component or library:
const ClientOnlyWrapper = ({ children }) => {
  const [isClient, setIsClient] = useState(false);

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

  return <>{isClient ? children : null}</>;
};

const WrappedModal = () => {
  return(
    <ClientOnlyWrapper>
       <Modal />
    <ClientOnlyWrapper/>
  )
}
Slovakian Wirehaired Pointer
Try creating an empty Div in layout, and reference it in your app like this:

/* Once the components are mounted, set a ref to the modal-root container in the rootlayout */
  useEffect(() => {
    containerRef.current = document.querySelector("#modal-root")
  }, []);
  
  /* When there is a modal in the context and the coontainer ref is set from useEffect, create a portal to push the modal to the rootLayout, otherwise return nothing */
  if (modal && containerRef.current) {
    return createPortal(<ModalHTML />, containerRef.current);
  } else {
    return null;
  }