React中FullCalendar的datesSet触发无限循环问题修复求助
解决FullCalendar datesSet事件触发React无限循环问题
问题场景
在React项目中使用FullCalendar库,通过datesSet事件识别页面渲染的日期范围,点击工具栏切换年月时触发了无限循环错误,错误信息如下:
Uncaught Error: Maximum update depth exceeded. This can happen when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate. React limits the number of nested updates to prevent infinite loops.
依赖版本
"@fullcalendar/core": "^6.1.4", "@fullcalendar/daygrid": "^5.11.4", "@fullcalendar/interaction": "^5.11.4", "@fullcalendar/moment": "^6.1.4", "@fullcalendar/react": "^5.10.1", "@fullcalendar/timegrid": "^5.11.4",
原代码
import { AdaptableCard, CalendarView } from "components/shared"; import React, { useCallback, useState } from "react"; const Calendario = (props) => { const [eventosComite] = useState([]); const [dados, setData] = useState({ start: "", end: "", }); const onDatesChange = useCallback( (arg) => { const { start, end } = arg; setData({ start: start, end: end, }); }, [setData] ); console.log(dados); return ( <AdaptableCard className="h-full mb-5" bodyClass="h-full"> <div className="lg:flex items-center justify-between mb-4"> <h3 className="mb-4 lg:mb-0">Calendário</h3> </div> <CalendarView editable selectable events={eventosComite} datesSet={onDatesChange} /> </AdaptableCard> ); }; export default Calendario;
问题原因
- 依赖版本不兼容:
@fullcalendar/core使用6.x版本,但其余大部分FullCalendar相关包为5.x,版本差异会导致组件内部逻辑异常,重复触发datesSet事件。 - 无意义的State更新:每次
datesSet触发时直接调用setData,即使日期范围未变化也会导致组件重渲染,重渲染后CalendarView可能再次触发datesSet,形成循环。 - 组件渲染逻辑问题:若
CalendarView是自定义组件,未做渲染优化(如未用React.memo缓存),父组件重渲染会导致CalendarView重复实例化,进而重复触发事件。
解决方案
1. 统一FullCalendar依赖版本
将所有@fullcalendar相关包升级至同一大版本(推荐6.x),避免版本冲突。修改package.json中的依赖:
"@fullcalendar/core": "^6.1.4", "@fullcalendar/daygrid": "^6.1.4", "@fullcalendar/interaction": "^6.1.4", "@fullcalendar/moment": "^6.1.4", "@fullcalendar/react": "^6.1.4", "@fullcalendar/timegrid": "^6.1.4",
执行npm install或yarn install更新依赖。
2. 优化State更新逻辑
在onDatesChange中先判断日期范围是否真的变化,仅当新旧值不同时才更新State,减少不必要的组件重渲染:
const onDatesChange = useCallback( (arg) => { const { start, end } = arg; // 对比新旧日期,避免无意义更新 if (dados.start !== start || dados.end !== end) { setData({ start: start, end: end, }); } }, [dados] // 依赖当前dados状态,确保对比准确 );
3. 优化CalendarView组件(若为自定义封装)
如果CalendarView是你项目中自定义的FullCalendar封装组件,用React.memo包裹它,避免父组件重渲染时重复创建Calendar实例:
import React from 'react'; import FullCalendar from '@fullcalendar/react'; // 导入所需的日历插件... const CalendarView = React.memo((props) => { // 原组件逻辑 return <FullCalendar {...props} />; }); export default CalendarView;
内容的提问来源于stack exchange,提问作者Zan
相关产品推荐
相关产品推荐

