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中又把视图设回月视图,导致状态来回切换最终回到月视图。
调整方案:
拆分视图切换与日期导航逻辑
onNavigate仅处理日期变化,计算对应视图的时间范围并加载事件,不修改currentViewonView负责处理视图切换,更新currentView并计算新视图的时间范围、加载事件
重构
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(); }); }
修正组件事件回调
onView回调先更新视图状态,再执行事件加载:onView={(view) => { this.setState({ currentView: view }, () => { this.startDateCal(this.state.selectedDate, view); }); }}onNavigate保持原有调用,不再修改视图:onNavigate={(date, view) => { this.startDateCal(date, view); }}
确保视图由状态驱动
组件defaultView绑定this.state.currentView,让视图切换与组件自身行为保持一致。
修改后,点击月视图日期标题时,组件会先切换到日视图,onView回调更新视图状态并加载日视图事件,onNavigate传递正确的日期与视图参数,不会再强制将视图改回月视图,解决页面回退问题。
内容的提问来源于stack exchange,提问作者Axen_Rangs
相关产品推荐
相关产品推荐

