React压缩错误#185求助:FullCalendar启用注释代码后报错
解决React-FullCalendar触发Minified React错误#185的问题
问题核心
错误#185对应的原始错误是Too many re-renders. React limits the number of renders to prevent an infinite loop.,即组件陷入了无限重渲染循环。从你注释的代码来看,问题出在eventsList状态更新与FullCalendar组件渲染的循环触发上。
触发原因
当你解除以下注释后:
- 启用
eventsList状态管理日历事件 - 将
events: eventsList传入FullCalendar配置 - 在API回调中调用
setEventsList(list)更新状态
会形成如下循环:
eventsList更新 → FullCalendar组件重新渲染- FullCalendar渲染时触发
datesSet回调 → 更新startDate/endDate状态 endDate变化触发useEffect→ 调用getAllCalendarAppointmentsAction获取数据- API回调中再次调用
setEventsList→ 回到第一步,循环往复
另外,calendarOptions在组件每次渲染时都会重新创建新对象,即使eventsList没变化,也会导致FullCalendar重复接收新props,加剧重渲染问题。
解决方案
1. 用useMemo缓存日历配置对象
避免每次渲染都生成新的calendarOptions,只有当依赖项变化时才更新:
// 恢复eventsList状态 const [eventsList, setEventsList] = useState([]) // 用useMemo缓存calendarOptions const calendarOptions = useMemo(() => ({ navLinks: true, dayMaxEvents: 1, editable: false, ref: calendarRef, selectable: true, nowIndicator: true, eventOverlap: false, slotMinTime: '06:00:00', slotMaxTime: '23:30:00', stickyHeaderDates: true, initialView: 'timeGridWeek', stickyFooterScrollbar: true, schedulerLicenseKey: '0599384492-fcs-1678752810', events: eventsList, // 恢复使用eventsList plugins: [ interactionPlugin, ScrollGridPlugin, dayGridPlugin, timeGridPlugin ], // 其余配置保持不变... }), [isMobile, view, eventsList, provider_id]) // 添加上所有依赖项
2. 避免不必要的状态更新
在API回调中,先对比新生成的事件列表与当前eventsList,只有不同时才更新状态:
// 先引入lodash的isEqual(或自行实现浅比较逻辑) import isEqual from 'lodash/isEqual' // 在getAllCalendarAppointmentsAction的回调中修改: callback: (res) => { let list = res.map((row) => { // 原有的事件转换逻辑保持不变 }) // 浅比较新列表与当前状态,不同才更新 if (!isEqual(list, eventsList)) { setEventsList(list) } }
3. 调整useEffect依赖项
如果success状态每次API调用都会触发变化,会导致useEffect重复执行,可以考虑移除success依赖,或者用ref跟踪是否需要重新获取数据:
// 替换原有的Appointments Action useEffect const initialLoadRef = useRef(true) useEffect(() => { if (endDate && !initialLoadRef.current) { dispatch( getAllCalendarAppointmentsAction({ // 原配置不变 }) ) } initialLoadRef.current = false }, [endDate]) // 移除success依赖,仅在endDate变化时触发
额外优化
可以直接将API获取的事件数据通过FullCalendar的events函数传入,跳过state中转,从根源避免循环:
const calendarOptions = useMemo(() => ({ // 其他配置不变 events: (info, successCallback) => { if (!provider_id || !info.startStr || !info.endStr) return const start = info.startStr.split('T')[0] const end = info.endStr.split('T')[0] dispatch( getAllCalendarAppointmentsAction({ offset: 0, limit: 100, startDate: start, endDate: end, providerId: provider_id, callback: (res) => { let list = res.map((row) => { // 原有的事件转换逻辑 }) successCallback(list) } }) ) }, // 其余配置不变 }), [provider_id, isMobile, view])
这种方式让FullCalendar主动请求数据,无需通过state管理事件列表,彻底避免重渲染循环。
内容的提问来源于stack exchange,提问作者Haris Ahmad
相关产品推荐
相关产品推荐

