Next.js客户端组件报错ReferenceError: document is not defined的解决方法
解决Next.js 13.1.6中Portal组件"document is not defined"错误
问题原因
即使给组件标记了"use client",在Next.js 13.1.6的App Router模式下,客户端组件仍会参与服务器端的初始渲染流程。此时浏览器环境还未初始化,document对象不存在,直接访问document.body就会抛出ReferenceError。
解决方案
方法1:使用useEffect确保客户端挂载后再创建Portal
useEffect钩子只会在客户端执行,通过它标记组件已在客户端挂载,再渲染Portal:
"use client" import type { ReactPortal } from "react" import { createPortal } from "react-dom" import { useEffect, useState } from "react" interface PortalProps { children: React.ReactNode } export function Portal(props: PortalProps): ReactPortal | null { const [isClientMounted, setIsClientMounted] = useState(false) useEffect(() => { setIsClientMounted(true) }, []) // 客户端未挂载时返回null,避免服务器端访问document if (!isClientMounted) { return null } return createPortal(props.children, document.body) }
方法2:直接判断document是否存在
通过检查document的类型,避免在服务器端执行时访问它:
"use client" import type { ReactPortal } from "react" import { createPortal } from "react-dom" interface PortalProps { children: React.ReactNode } export function Portal(props: PortalProps): ReactPortal | null { // 服务器端环境下document不存在,返回null if (typeof document === "undefined") { return null } return createPortal(props.children, document.body) }
两种方法都能避免服务器端渲染阶段访问document,解决报错问题。优先推荐方法1,因为它更贴合React的生命周期,确保组件在客户端完全挂载后再渲染Portal内容。
内容的提问来源于stack exchange,提问作者Roman Mahotskyi
相关产品推荐
相关产品推荐

