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

React FullCalendar中如何将选中月份日期范围存入state并避免无限重渲染

解决FullCalendar datesSet触发无限重渲染问题

你遇到的问题核心是:每次datesSet触发时直接调用setDateRange(arg)会导致组件重渲染,而FullCalendar重新渲染后又会再次触发datesSet,形成无限循环。

修复步骤:

  • 用useRef存储上一次的日期范围,对比当前范围是否真正变化,仅在变化时更新state
  • 避免直接存储datesSet返回的完整arg对象(因为每次触发的arg可能是新对象,即使日期范围没变,也会触发state更新)

修改后的代码示例:

import { useState, useRef } from 'react';
// ...其他导入

const YourComponent = () => {
  const [dateRange, setDateRange] = useState<{ start: Date; end: Date }>();
  const prevDateRangeRef = useRef<{ start: Date; end: Date }>();

  const handleDatesSet = (arg: any) => {
    // 提取关键的日期范围字段
    const newRange = { start: arg.start, end: arg.end };
    
    // 对比是否和上一次的范围一致,避免不必要的state更新
    if (!prevDateRangeRef.current || 
        prevDateRangeRef.current.start.getTime() !== newRange.start.getTime() || 
        prevDateRangeRef.current.end.getTime() !== newRange.end.getTime()) {
      setDateRange(newRange);
      prevDateRangeRef.current = newRange;
    }
  };

  return (
    <Box flex="1 1 100%" ml="15px" sx={{backgroundColor: 'white', borderRadius:3, boxShadow: '0px 2px 4px 1px rgba(0,0,0,0.25)', p:3, marginBottom:2, width:'100%'}}>
      <FullCalendar
        height="75vh"
        locales={[enLocale, frLocale]}
        locale={frLocale}
        weekNumberCalculation="ISO"
        plugins={[
          dayGridPlugin,
          timeGridPlugin,
          interactionPlugin,
          listPlugin,
        ]}
        headerToolbar={{
          left: "prev,next today",
          center: "title",
          right: rightElement,
        }}
        initialView="dayGridMonth" // 修复原代码的单引号语法错误
        editable={true}
        selectable={true}
        selectMirror={true}
        datesSet={handleDatesSet}
        dayMaxEvents={true}
        select={handleDateClick}
        eventChange={handleEventChange}
        eventClick={handleEventClick}
        eventsSet={(events:any) => setCurrentEvents(events)}
        initialEvents={newArray}
      />
    </Box>
  );
};

关键说明:

  1. 用useRef跟踪上一次范围:通过对比时间戳(getTime())判断日期是否真正变化,避免因对象引用变化导致的无意义更新
  2. 只存储必要字段:不再存储完整的arg对象,只保留start和end日期,减少state更新的触发频率
  3. 修复语法错误:原代码中initialView={dayGridMonth'}存在单引号位置错误,已修正为initialView="dayGridMonth"

这样修改后,只有当用户切换月份或视图导致日期范围真正变化时,才会更新dateRange state,彻底解决无限重渲染问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 14:12:20