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

React动态选择数组元素渲染当日及前后日程表问题求助

问题分析与解决方案

核心问题梳理

  1. 日期比较逻辑错误:直接用===或</>比较moment对象,且未忽略时分秒导致日期匹配失败
  2. 异步状态更新时序问题:调用setCurrentIndex后立即执行initPreviousAndNext,此时currentIndex尚未完成更新
  3. 状态冗余与取值错误:依赖未更新的previousIndex/nextIndex获取日程,导致前/后一日数据无法正确设置

具体修复步骤

1. 修正日期比较逻辑

使用moment官方提供的isSame、isBefore、isAfter方法,并指定'day'粒度忽略时分秒,确保日期匹配准确:

  • 替换moment() < moment(...)为moment().isBefore(moment(...), 'day')
  • 替换moment() > moment(...)为moment().isAfter(moment(...), 'day')
  • 替换moment(...) === moment()为moment(...).isSame(moment(), 'day')

2. 调整initPreviousAndNext调用时机

由于setCurrentIndex是异步操作,不能在initCurrentDay中直接调用initPreviousAndNext,新增依赖currentIndex的useEffect,当索引更新后再初始化前后日数据:

useEffect(() => {
  if (currentIndex !== undefined && timetables.length > 0) {
    initPreviousAndNext()
  }
}, [currentIndex, timetables])

3. 修复前后日数据取值逻辑

无需依赖previousIndex/nextIndex状态,直接通过currentIndex计算索引并获取日程,避免异步状态更新导致的取值错误:

function initPreviousAndNext() {
  if (currentIndex === undefined) return
  // 设置前一日
  setPreviousDay(currentIndex > 0 ? timetables[currentIndex - 1] : undefined)
  // 设置后一日
  setNextDay(currentIndex < timetables.length - 1 ? timetables[currentIndex + 1] : undefined)
}

4. 移除冗余状态(可选优化)

previousIndex和nextIndex可通过currentIndex直接计算,无需单独维护,删除这两个状态变量可减少状态同步问题。

修改后的完整代码

import { useState, useEffect } from 'react'
import moment from 'moment'

export function MainPage() {
  const [previousDay, setPreviousDay] = useState<ITimetable>()
  const [currentDay, setCurrentDay] = useState<ITimetable>()
  const [nextDay, setNextDay] = useState<ITimetable>()

  const [currentIndex, setCurrentIndex] = useState<number>()

  const { timetables, loading, error } = useTimetables()
  
  useEffect(() => {
    initCurrentDay()
  }, [timetables])

  useEffect(() => {
    if (currentIndex !== undefined && timetables.length > 0) {
      initPreviousAndNext()
    }
  }, [currentIndex, timetables])

  function initCurrentDay() {
    if (timetables.length === 0) return

    const today = moment()
    const firstDay = moment(timetables[0].date, "dddd - DD/MM/YY")
    const lastDay = moment(timetables[timetables.length - 1].date, "dddd - DD/MM/YY")

    if (today.isBefore(firstDay, 'day')) {
      setCurrentDay(timetables[0])
      setCurrentIndex(0)
    } else if (today.isAfter(lastDay, 'day')) {
      setCurrentDay(timetables[timetables.length - 1])
      setCurrentIndex(timetables.length - 1)
    } else {
      const matched = timetables.find(item => {
        return moment(item.date, "dddd - DD/MM/YY").isSame(today, 'day')
      })
      if (matched) {
        const index = timetables.indexOf(matched)
        setCurrentDay(matched)
        setCurrentIndex(index)
      }
    }
  }

  function initPreviousAndNext() {
    if (currentIndex === undefined) return
    
    setPreviousDay(currentIndex > 0 ? timetables[currentIndex - 1] : undefined)
    setNextDay(currentIndex < timetables.length - 1 ? timetables[currentIndex + 1] : undefined)
  }
  
  return (
    <>
      <NavigationPanel></NavigationPanel>
      { loading && <div>Loading...</div>}
      { error && <div>{ error }</div>}
      { timetables.length > 0 &&
        <div className="timetables-view">
          <div className="previous-timetable">
            {previousDay && <Timetable timetable={ previousDay } key={ previousDay.id }></Timetable> }
          </div>
          {currentDay &&
            <div className="current-timetable">
              {previousDay && <img src={ arrowLeft } alt="切换到前一日"></img>}
              <CurrentTimetable timetable={ currentDay } key={ currentDay.id }></CurrentTimetable>
              {nextDay && <img src={ arrowRight } alt="切换到后一日"></img>}
            </div>
          }
          <div className="next-timetable">
            { nextDay && <Timetable timetable={ nextDay } key={ nextDay.id }></Timetable> }
          </div>
        </div>
      }
    </>
  );
}

额外说明

调试时currentDay偶尔显示undefined是因为useTimetables加载数据需要时间,页面能显示当日是因为timetables.length > 0的判断会等待数据加载完成后才渲染,此时currentDay已被正确设置。若需支持手动切换前后日,只需在箭头点击事件中修改currentIndex,前后日数据会自动更新。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 03:35:04