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

React周历开发问题:多选日期功能异常

问题分析与解决方案

你的核心问题在于**active数组存储的是对象,但判断激活状态和移除逻辑都在操作字符串**,导致匹配失败,所以active类无法正确添加/移除。下面是具体的修正方案:

核心问题拆解

  • 当前active里存的是{hour: "...", hourId: x, dayId: y}格式的对象,但isActive = active.includes(hour.hour)是在数组中查找字符串,永远返回false
  • 移除时用active.filter(current => current !== hour.hour)也是用字符串和对象对比,根本删不掉目标项

修正后的代码

const [active, setActive] = useState([])

// 抽离判断逻辑,复用性更强
const isSlotActive = (dayId, hourId) => {
  return active.some(item => item.dayId === dayId && item.hourId === hourId)
}

// 抽离点击事件处理函数
const toggleSlot = (dayId, hourId, hour) => {
  setActive(prev => {
    const isActive = prev.some(item => item.dayId === dayId && item.hourId === hourId)
    if (isActive) {
      // 移除对应时段:过滤掉dayId和hourId都匹配的项
      return prev.filter(item => !(item.dayId === dayId && item.hourId === hourId))
    } else {
      // 添加新时段
      return [...prev, { hour, hourId, dayId }]
    }
  })
}

...

<div className="calendar-days"> 
  {dayNames.map((item, dayIndex) => 
    <div className="day-column" key={dayIndex}>
      <h2>{item.longName}</h2>
      {hours.map((hour, hourIndex) => {
        const isActive = isSlotActive(dayIndex, hourIndex)
        return (
          <button
            key={`${dayIndex}-${hourIndex}`} // 用组合key保证唯一性
            onClick={() => toggleSlot(dayIndex, hourIndex, hour.hour)}
            className={`hour ${isActive ? "active" : ""}`}
          >
            {hour.hour} 
          </button>
        )
      })}
    </div>
  )}  
</div>

额外优化建议

  1. 简化基础数据结构:hours数组不需要存对象,直接用字符串数组更简洁:

    export const hours = ["7:00", "7:45", "8:30", "9:15", "10:00", "10:45", ...]
    

    后续映射时直接用hour代替hour.hour即可。

  2. 优化选中状态的存储:如果只需要判断是否选中,不需要额外字段,可以用Set存储唯一标识(比如${dayId}-${hourId}),查找和删除效率更高:

    const [activeSlots, setActiveSlots] = useState(new Set())
    
    const isSlotActive = (dayId, hourId) => {
      return activeSlots.has(`${dayId}-${hourId}`)
    }
    
    const toggleSlot = (dayId, hourId, hour) => {
      setActiveSlots(prev => {
        const key = `${dayId}-${hourId}`
        const newSet = new Set(prev)
        if (newSet.has(key)) {
          newSet.delete(key)
        } else {
          newSet.add(key)
          // 如果需要保留完整数据,可以同时维护一个数组,或者用Map存储key到对象的映射
        }
        return newSet
      })
    }
    
  3. 避免重复渲染:如果组件较大,可以考虑把单个时段按钮抽成独立组件,减少不必要的重渲染。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 07:15:34