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

React Big Calendar onNavigate触发后日期导航异常解决方案咨询

问题描述

我修改了react-big-calendar,让它在onNavigate触发时根据时间范围加载事件。但现在在月视图中点击日期标题尝试导航到指定日期时,页面会重新加载并回到月视图。排查后发现是onNavigate触发时修改日期导致的,且未找到与日期标题相关的其他props。

日历组件代码
<MyCalendar
  dayPropGetter={this.dayPropGetter}
  localizer={localizer}
  selectable
  events={this.state.eventData}
  startAccessor="EventDate"
  endAccessor="EndDate"
  eventPropGetter={this.eventStyleGetter}
  onSelectSlot={this.onSelectSlot}
  components={{
    event: this.renderEvent
  }}
  onSelectEvent={this.onSelectEvent}
  defaultDate={this.state.selectedDate}
  views={{
    day: true,
    week: true,
    month: true,
    agenda: true,
    work_week: Year
  }}
  defaultView={this.state.currentView}
  messages={{
    'today': strings.todayLabel,
    'previous': strings.previousLabel,
    'next': strings.nextLabel,
    'month': strings.monthLabel,
    'week': strings.weekLabel,
    'day': strings.dayLable,
    'showMore': total => `+${total} ${strings.showMore}`,
    'work_week': strings.yearHeaderLabel
  }}
  onNavigate={(date, view) => {
    this.startDateCal(date, view);
    console.log('date', date, 'view', view);
  }}
  onView={(view) => this.startDateCal(this.state.selectedDate, view)}
  onShowMore={() => {this.setState({ currentView: 'day' });}}
/>
事件加载逻辑代码
private async startDateCal(date: Date, view: string) {
  this.setState({ isloading: true });
  
  if (view === 'month') {
    this.startDate = moment(date).startOf('month').toDate();
    this.endDate = moment(date).endOf('month').toDate();
    this.setState({ currentView: 'month' });
    this.setState({ selectedDate: date});
  } else if (view === 'day') {
    this.startDate = moment(date).startOf('day').toDate();
    this.endDate = moment(date).endOf('day').toDate();
    this.setState({ currentView: 'day' });
    this.setState({ selectedDate: date });
  } else if (view === 'week') {
    this.startDate = moment(date).startOf('week').toDate();
    this.endDate = moment(date).endOf('week').toDate();
    this.setState({ currentView: 'week' });
    this.setState({ selectedDate: date });
  }

  this.loadEvents();
}
解决办法

问题核心是onNavigate与onView的逻辑冲突,以及startDateCal中强制设置currentView覆盖了组件本身的视图切换行为。点击月视图日期标题时,组件会自动尝试切换到日视图,但代码在onNavigate中又把视图设回月视图,导致状态来回切换最终回到月视图。

调整方案:

  1. 拆分视图切换与日期导航逻辑

    • onNavigate仅处理日期变化,计算对应视图的时间范围并加载事件,不修改currentView
    • onView负责处理视图切换,更新currentView并计算新视图的时间范围、加载事件
  2. 重构startDateCal方法
    移除方法中对currentView的设置,统一处理状态更新,避免多次setState导致的混乱:

private async startDateCal(date: Date, view: string) {
  this.setState({ isloading: true });
  let startDate, endDate;

  switch(view) {
    case 'month':
      startDate = moment(date).startOf('month').toDate();
      endDate = moment(date).endOf('month').toDate();
      break;
    case 'day':
      startDate = moment(date).startOf('day').toDate();
      endDate = moment(date).endOf('day').toDate();
      break;
    case 'week':
      startDate = moment(date).startOf('week').toDate();
      endDate = moment(date).endOf('week').toDate();
      break;
    default:
      startDate = date;
      endDate = date;
  }

  this.setState({
    selectedDate: date,
    startDate,
    endDate
  }, () => {
    // 状态更新完成后再加载事件
    this.loadEvents();
  });
}
  1. 修正组件事件回调

    • onView回调先更新视图状态,再执行事件加载:
      onView={(view) => {
        this.setState({ currentView: view }, () => {
          this.startDateCal(this.state.selectedDate, view);
        });
      }}
      
    • onNavigate保持原有调用,不再修改视图:
      onNavigate={(date, view) => {
        this.startDateCal(date, view);
      }}
      
  2. 确保视图由状态驱动
    组件defaultView绑定this.state.currentView,让视图切换与组件自身行为保持一致。

修改后,点击月视图日期标题时,组件会先切换到日视图,onView回调更新视图状态并加载日视图事件,onNavigate传递正确的日期与视图参数,不会再强制将视图改回月视图,解决页面回退问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 19:29:55