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>
额外优化建议
简化基础数据结构:
hours数组不需要存对象,直接用字符串数组更简洁:export const hours = ["7:00", "7:45", "8:30", "9:15", "10:00", "10:45", ...]后续映射时直接用
hour代替hour.hour即可。优化选中状态的存储:如果只需要判断是否选中,不需要额外字段,可以用
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 }) }避免重复渲染:如果组件较大,可以考虑把单个时段按钮抽成独立组件,减少不必要的重渲染。
内容的提问来源于stack exchange,提问作者MarcinB
相关产品推荐
相关产品推荐

