解决Next.js集成react-calendly时document未定义的错误
你遇到的核心问题是Next.js服务端渲染阶段无法访问浏览器的document对象,而PopupButton的rootElement属性需要传入DOM节点。这里给你两种可行的解决方式:
方法一:用useEffect在客户端获取DOM节点
利用React的useEffect钩子(仅在客户端执行)来获取目标DOM元素,避免服务端渲染时的错误:
修改你的Home组件代码:
import styles from '../styles/Home.module.css' import Head from 'next/head' import { PopupButton } from 'react-calendly' import { useState, useEffect } from 'react' export default function Home() { const [rootElement, setRootElement] = useState(null) useEffect(() => { // 客户端渲染时获取DOM节点 setRootElement(document.getElementById("body")) }, []) return ( <div className="home"> <Head> <title>Homepage</title> </Head> <div className="cal_div"> {/* 只有获取到DOM节点后才渲染按钮 */} {rootElement && ( <PopupButton url="https://calendly.com/my_url" rootElement={rootElement} text="Click here to schedule!" /> )} </div> </div> ) }
方法二:动态导入组件并禁用SSR
通过Next.js的dynamic函数导入PopupButton,强制组件仅在客户端渲染,这样就能直接访问document:
修改Home组件的导入部分和代码:
import styles from '../styles/Home.module.css' import Head from 'next/head' import dynamic from 'next/dynamic' // 动态导入PopupButton,禁用SSR const PopupButton = dynamic( () => import('react-calendly').then(mod => mod.PopupButton), { ssr: false } ) export default function Home() { return ( <div className="home"> <Head> <title>Homepage</title> </Head> <div className="cal_div"> <PopupButton url="https://calendly.com/my_url" rootElement={document.getElementById("body")} text="Click here to schedule!" /> </div> </div> ) }
额外注意
你代码里的document.getElementsById是拼写错误,正确的应该是document.getElementById(单数形式),这个错误会导致即使解决了SSR问题,也无法找到目标DOM节点,记得修正。
内容的提问来源于stack exchange,提问作者lukedawg
相关产品推荐
相关产品推荐

