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

在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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 15:08:12