如何在React FullCalendar中以函数形式正确加载动态事件?
React FullCalendar 动态加载事件的正确实现方案
问题核心
你遇到的两个关键问题:
- 直接调用函数赋值
events={returnEvent()}会触发无限渲染循环,因为组件每次渲染都会执行函数,setEvents又触发重新渲染,导致API持续调用。 - 用箭头函数
events={() => returnEvent()}无效,因为FullCalendar对events属性的函数格式有特定要求,不是随便返回数组的函数都能生效。
方案1:一次性初始化加载所有事件(适合小数据量场景)
通过useEffect在组件挂载时仅执行一次API请求,将结果存入状态后直接传给FullCalendar:
import { useState, useEffect, useRef } from 'react'; import FullCalendar from '@fullcalendar/react'; import dayGridPlugin from '@fullcalendar/daygrid'; const Calendar = () => { const [events, setEvents] = useState([]); const calendarRef = useRef(null); // 组件挂载时仅加载一次事件 useEffect(() => { const loadEvents = async () => { // 替换为你的数据库请求逻辑 const response = await fetch('/your-api-endpoint'); const fetchedEvents = await response.json(); setEvents(fetchedEvents); }; loadEvents(); }, []); // 空依赖数组确保只执行一次 return ( <FullCalendar plugins={[dayGridPlugin]} timeZone={'Europe/London'} now={new Date().toISOString()} ref={calendarRef} initialView="dayGridMonth" height="100%" events={events} // 直接传入状态数组 /> ); }; export default Calendar;
方案2:按需加载事件(适合大数据量,随视图切换加载对应数据)
利用FullCalendar内置的按需加载机制,events属性传入异步函数,FullCalendar会自动传入当前视图的时间范围(start/end参数),仅加载对应时间段的事件:
import { useRef } from 'react'; import FullCalendar from '@fullcalendar/react'; import dayGridPlugin from '@fullcalendar/daygrid'; const Calendar = () => { const calendarRef = useRef(null); // 按需加载事件,FullCalendar自动传入当前视图的时间范围 const fetchEvents = async (fetchInfo) => { // 基于当前视图的start和end请求对应数据 const response = await fetch(`/your-api-endpoint?start=${fetchInfo.start.toISOString()}&end=${fetchInfo.end.toISOString()}`); return response.json(); // 返回Promise,FullCalendar自动处理事件渲染 }; return ( <FullCalendar plugins={[dayGridPlugin]} timeZone={'Europe/London'} now={new Date().toISOString()} ref={calendarRef} initialView="dayGridMonth" height="100%" events={fetchEvents} // 直接传入异步函数 /> ); }; export default Calendar;
静态数据用函数形式的正确写法
如果是静态数据,需要直接将函数传给events(不带括号,FullCalendar会主动调用该函数获取事件):
const getStaticEvents = () => { const todayStr = new Date().toISOString().replace(/T.*$/, ''); return [ { id: '1', title: '全天事件', start: todayStr }, { id: '2', title: '定时事件', start: `${todayStr}T12:00:00` } ]; }; // 正确用法 <FullCalendar // ...其他属性 events={getStaticEvents} // 直接传函数,不要加括号或嵌套箭头函数 />
错误原因总结
events={returnEvent()}:每次组件渲染都会执行函数,触发setEvents导致无限渲染循环,API反复调用。events={() => returnEvent()}:FullCalendar期望events函数直接返回事件数组或Promise,而你传入的是返回函数的箭头函数,不符合要求。
内容的提问来源于stack exchange,提问作者Patrick Johnson
相关产品推荐
相关产品推荐

