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

使用FullCalendar React的eventContent导致事件重复渲染问题求助

问题

我在使用FullCalendar React自定义周历视图的事件显示时遇到了性能问题:

  • 只要设置了eventContent(哪怕只是返回事件标题的基础实现),切换上一周/下一周时所有事件都会重新渲染;但不设置eventContent时,事件仅渲染一次。
  • 我的日历需要加载数千条股票市场企业财报事件,事件通过回调函数结合fetchEvents按当前视图起止日期从JSON文件获取。
  • 希望实现包含企业名称(存在event.extendedProps)、开始时间、股票代码(设为event标题)的自定义事件视图,同时避免重复渲染提升性能。

代码示例:

const eventContent = (eventInfo) => {
    const {event} = eventInfo;
    return (<span>{event.title}</span>)
}
<FullCalendar
          plugins={[dayGridPlugin]}
          initialView="dayGridWeek"
          weekends={true}
          events={events}
          eventDisplay="block"
          eventOrder="start, title"
          timeZone="local"
          eventContent={eventContent}
          headerToolbar={{
            start: "prev",
            center: "title",
            end: "next",
          }}
          allDaySlot={false}
        />

解决方案

1. 用React.memo缓存自定义事件组件

FullCalendar每次切换视图时会重新调用eventContent生成新的React元素,哪怕事件数据没变化。用React.memo包裹自定义事件组件,只有当传入的事件数据发生变化时才会重新渲染。

修改代码:

// 定义纯组件并缓存
const EventContent = React.memo(({ event }) => {
  return (
    <span>
      {event.title} - {event.extendedProps.companyName}
    </span>
  );
});

// 传入eventContent
const eventContent = (eventInfo) => {
  return <EventContent event={eventInfo.event} />;
};

2. 稳定事件数据的引用

确保events回调返回的事件对象引用稳定——每次获取数据后,用唯一标识(比如股票代码)复用对象引用,避免因对象重新创建触发不必要的渲染。可以结合useMemo和useCallback缓存事件数据和获取函数:

const fetchEvents = useCallback((info, successCallback) => {
  fetch(`/your-data-url?start=${info.startStr}&end=${info.endStr}`)
    .then(res => res.json())
    .then(data => {
      const processedEvents = data.map(item => ({
        id: item.stockCode, // 用唯一ID确保引用稳定
        title: item.stockCode,
        start: item.reportDate,
        extendedProps: {
          companyName: item.companyName
        }
      }));
      successCallback(processedEvents);
    });
}, []);

// 缓存events配置,避免每次渲染生成新函数
const events = useMemo(() => fetchEvents, [fetchEvents]);

3. 用原生DOM操作替代React组件渲染

如果自定义内容逻辑简单,可以绕过React的渲染机制,通过eventDidMount钩子在事件首次挂载时手动插入DOM内容,只有事件被销毁重建时才会重新执行,减少重复计算:

const eventDidMount = (info) => {
  const eventEl = info.el;
  eventEl.innerHTML = '';
  const contentEl = document.createElement('span');
  contentEl.textContent = `${info.event.title} - ${info.event.extendedProps.companyName}`;
  eventEl.appendChild(contentEl);
};

// 修改FullCalendar配置,移除eventContent,添加eventDidMount
<FullCalendar
  plugins={[dayGridPlugin]}
  initialView="dayGridWeek"
  weekends={true}
  events={events}
  eventDisplay="block"
  eventOrder="start, title"
  timeZone="local"
  headerToolbar={{
    start: "prev",
    center: "title",
    end: "next",
  }}
  allDaySlot={false}
  eventDidMount={eventDidMount}
/>

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 03:39:55