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

FullCalendar React:datesSet调用getApi报错(无法读取undefined的getApi)

解决React中FullCalendar v6动态修改slotMinTime/slotMaxTime的报错问题

问题原因

  1. 日期判断逻辑错误:datesSet回调的参数不是直接的Date对象,而是包含start/end等属性的DatesSetArg对象,你错误调用了infoDate.getDate(),这会引发隐式错误,间接导致后续ref访问异常。
  2. 循环触发回调:调用setOption修改时间配置会触发日历重新渲染,进而再次触发datesSet回调形成循环。循环过程中calendarRef.current可能未完成更新,导致第二次执行时出现undefined。
  3. 直接操作实例不符合React数据流:直接调用日历API修改配置,脱离了React的响应式状态管理,容易引发状态不同步问题。

解决方案

方案1:修复现有代码(直接操作API)

修正日期判断逻辑,增加配置差异检查避免循环,同时增加ref存在性判断:

datesSet={(info) => {
  // 确保ref存在再执行后续操作
  if (!calendarRef.current) return;
  const calendarApi = calendarRef.current.getApi();
  // 获取当前视图显示日期的星期几(0=周日,6=周六)
  const currentDay = info.start.getDay();
  
  let targetMinTime, targetMaxTime;
  if (currentDay === 6) { // 周六
    targetMinTime = '08:00:00';
    targetMaxTime = '11:00:00';
  } else if (currentDay === 1) { // 周一
    targetMinTime = '10:00:00';
    targetMaxTime = '18:00:00';
  } else {
    // 其他日期默认配置
    targetMinTime = '16:00:00';
    targetMaxTime = '19:00:00';
  }

  // 仅当配置不同时才修改,避免循环触发datesSet
  const currentMinTime = calendarApi.getOption('slotMinTime');
  const currentMaxTime = calendarApi.getOption('slotMaxTime');
  if (currentMinTime !== targetMinTime || currentMaxTime !== targetMaxTime) {
    calendarApi.setOption('slotMinTime', targetMinTime);
    calendarApi.setOption('slotMaxTime', targetMaxTime);
  }
}}

方案2:React响应式状态驱动(推荐)

遵循React单向数据流,用状态管理时间配置,通过props传递给日历组件:

import { useState, useRef } from 'react';
import FullCalendar from '@fullcalendar/react';
import timeGridPlugin from '@fullcalendar/timegrid';

function MyCalendar() {
  const [slotRange, setSlotRange] = useState({
    slotMinTime: '16:00:00',
    slotMaxTime: '19:00:00'
  });
  const calendarRef = useRef(null);

  const handleDatesSet = (info) => {
    const currentDay = info.start.getDay();
    let newSlotRange;

    if (currentDay === 6) { // 周六
      newSlotRange = { slotMinTime: '08:00:00', slotMaxTime: '11:00:00' };
    } else if (currentDay === 1) { // 周一
      newSlotRange = { slotMinTime: '10:00:00', slotMaxTime: '18:00:00' };
    } else {
      newSlotRange = { slotMinTime: '16:00:00', slotMaxTime: '19:00:00' };
    }

    setSlotRange(newSlotRange);
  };

  return (
    <FullCalendar
      ref={calendarRef}
      plugins={[timeGridPlugin]}
      initialView="timeGridDay"
      datesSet={handleDatesSet}
      // 直接传递状态作为配置
      {...slotRange}
      customButtons={{
        addEventButton: {
          text: 'Prendre rendez-vous',
          click: function () {
            const dateStr = prompt('Enter a date in YYYY-MM-DD format');
            const date = new Date(dateStr + 'T00:00:00');
            if (!isNaN(date.valueOf())) {
              calendarRef.current.getApi().addEvent({
                title: 'dynamic event',
                start: date,
                allDay: true
              });
            } else {
              alert('Invalid date.');
            }
          }
        }
      }}
    />
  );
}

方案优势说明

方案2完全遵循React的状态驱动UI理念,无需直接操作日历实例API,避免了异步更新导致的状态不一致问题,代码更易维护,也符合React开发的最佳实践。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 12:35:15