FullCalendar React:datesSet调用getApi报错(无法读取undefined的getApi)
解决React中FullCalendar v6动态修改slotMinTime/slotMaxTime的报错问题
问题原因
- 日期判断逻辑错误:
datesSet回调的参数不是直接的Date对象,而是包含start/end等属性的DatesSetArg对象,你错误调用了infoDate.getDate(),这会引发隐式错误,间接导致后续ref访问异常。 - 循环触发回调:调用
setOption修改时间配置会触发日历重新渲染,进而再次触发datesSet回调形成循环。循环过程中calendarRef.current可能未完成更新,导致第二次执行时出现undefined。 - 直接操作实例不符合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
相关产品推荐
相关产品推荐

