在Next.js中导入@fullcalendar/react,如何避免Hydration失败警告?
问题原因及解决方案
这个 hydration 不匹配错误的核心原因是:FullCalendar 依赖浏览器环境的 API(比如 window、document),而 Next.js 的 SSR/SSG 模式下,服务器端渲染时没有这些浏览器 API,导致服务器生成的 DOM 结构和客户端最终渲染的 DOM 不一致,在触发预加载事件时,这种差异被 React 检测到并抛出错误。FullCalendar 本身并非为服务器端渲染设计,因此和 Next.js 的 SSR 存在兼容性冲突。
解决方法
1. 动态导入 FullCalendar,禁用 SSR
使用 Next.js 的 dynamic 函数导入 FullCalendar,强制组件仅在客户端渲染,避免服务器端尝试渲染它导致的 DOM 差异。
修改你的组件代码如下:
import dynamic from 'next/dynamic' import listPlugin from '@fullcalendar/list' import dayGridPlugin from '@fullcalendar/daygrid' import timeGridPlugin from '@fullcalendar/timegrid' import { CalendarType } from './types' // 动态导入FullCalendar,禁用SSR const FullCalendar = dynamic(() => import('@fullcalendar/react'), { ssr: false, loading: () => <div>加载日历中...</div> // 可选:添加加载占位提示 }) const Calendar = ({ events, eventClick }: CalendarType) => { const views = { dayGridMonth: { buttonText: 'Month' }, timeGridWeek: { buttonText: 'Week' }, timeGridDay: { buttonText: 'Day' }, listMonth: { buttonText: 'List' }, } return ( <FullCalendar plugins={[dayGridPlugin, timeGridPlugin, listPlugin]} initialView="dayGridMonth" headerToolbar={{ left: 'prev,next today', center: 'title', right: 'dayGridMonth,timeGridWeek,timeGridDay,listMonth', }} views={views} contentHeight="auto" events={events} eventClick={eventClick} /> ) } export default Calendar
2. 确保事件数据前后一致
如果你的 events 数据是从服务端获取的,要保证 SSR/SSG 阶段获取的数据和客户端 hydration 阶段获取的数据完全一致。比如使用 getStaticProps 或 getServerSideProps 统一获取数据,避免客户端额外请求导致数据差异引发 DOM 不匹配。
3. 延迟客户端特定逻辑
如果 eventClick 回调中涉及仅客户端可用的 API(比如操作 window),可以用 useEffect 延迟绑定,确保逻辑仅在客户端执行:
import { useEffect, useState } from 'react' const Calendar = ({ events, eventClick }: CalendarType) => { const [clientEventClick, setClientEventClick] = useState(null) useEffect(() => { // 仅在客户端设置事件点击回调 setClientEventClick(eventClick) }, [eventClick]) // ...其他原有代码 return ( <FullCalendar // ...其他props eventClick={clientEventClick} /> ) }
内容的提问来源于stack exchange,提问作者János
相关产品推荐
相关产品推荐

