You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

NextJS中使用createPortal实现模态框报document未定义如何解决

报错原因

Next.js 默认会在服务端执行组件渲染逻辑,而服务端环境不存在浏览器专属的 document 全局对象,你直接在组件顶层执行 document.getElementById 就会触发该报错。另外你的代码还存在几处其他问题,同步修复即可。

修复步骤
  • 第一步:修正你 _document.js 里的节点拼写错误,确保id和你查询的名称一致:
<div id="modal-overlay"></div>

你之前步骤里写的id为modal-overaly属于拼写错误,会导致后续即便在客户端也拿不到目标节点。

  • 第二步:修复Modal组件的报错,有两种常用方案可选:

方案1:使用useEffect将DOM查询逻辑移到客户端执行

无需修改父组件导入方式,直接调整Modal组件代码即可,适配TS类型后的完整代码如下:

import { createPortal } from "react-dom";
import { useEffect, useRef, useState } from "react";

// 定义组件Props的TS类型
interface ModalProps {
  show: boolean;
}

const Modal = ({ show }: ModalProps) => {
  // 标记是否已挂载到客户端
  const [isClient, setIsClient] = useState(false);
  // 存储portal目标节点
  const portalNodeRef = useRef<HTMLElement | null>(null);

  useEffect(() => {
    setIsClient(true);
    portalNodeRef.current = document.getElementById("modal-overlay");
  }, []);

  // 未到客户端、不展示、未拿到节点时都返回null
  if (!isClient || !show || !portalNodeRef.current) return null;

  return createPortal(
    <div>
      <h1>
        Thank you for your inquire! We have received your message! Demelo
        Dining is ready to serve your upcoming event.
      </h1>
    </div>,
    portalNodeRef.current
  );
};

export default Modal;

同时要修正你之前的Props解构错误:你原有代码里写的const { showModal } = props.show是错误写法,直接传入show参数即可,父组件调用时写<Modal show={showModal} />就可以正常使用。

方案2:用Next.js的dynamic导入关闭组件服务端渲染

如果你不想修改Modal组件的逻辑,可以直接在父组件导入Modal时关闭SSR,这样Modal组件只会在客户端加载,自然不会有服务端找不到document的问题:

父组件导入代码:

import dynamic from "next/dynamic";
// 导入Modal时关闭服务端渲染
const Modal = dynamic(() => import("./Modal"), { ssr: false });

调整后的Modal组件简化代码:

import { createPortal } from "react-dom";

interface ModalProps {
  show: boolean;
}

const Modal = ({ show }: ModalProps) => {
  if (!show) return null;
  const portalElement = document.getElementById("modal-overlay");
  if (!portalElement) return null;

  return createPortal(
    <div>
      <h1>
        Thank you for your inquire! We have received your message! Demelo
        Dining is ready to serve your upcoming event.
      </h1>
    </div>,
    portalElement
  );
};

export default Modal;

内容的提问来源于stack exchange,提问作者Felipe

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 06:15:02