React Native日历应用事件展开异常:点击单个事件全部切换详情
解决React Native日历事件独立展开/收起的问题
你的问题核心在于所有事件共用了同一个全局状态,点击单个事件时触发的是全局状态变更,导致所有事件同步切换展开/收起状态。要实现单个事件独立控制,需要为每个事件维护独立的展开状态,具体修改方案如下:
1. 替换全局状态为事件级状态
把原来的isDetailed和isBlock单个布尔值,改成存储展开事件标识(索引或唯一ID)的数组,精准控制每个事件的状态:
// 替换原有的isDetailed、isBlock状态 const [expandedEventIndexes, setExpandedEventIndexes] = useState([]);
2. 修改切换函数,针对单个事件操作
更新toggleView函数,传入当前事件的索引,判断该索引是否在展开数组中,实现单个事件的状态切换:
const toggleView = (index) => { setExpandedEventIndexes(prevState => { if (prevState.includes(index)) { // 若已展开,移除该索引以收起 return prevState.filter(i => i !== index); } else { // 若未展开,添加该索引以展开 return [...prevState, index]; } }); };
3. 渲染时根据当前事件状态控制显示
在事件列表的渲染逻辑中,检查当前事件的索引是否在展开数组里,以此控制详情文本的显示和图标的切换:
<Text style={styles.eventsTitle}>Events for {dateSelected}:</Text> <ScrollView style={{ height: (calendarHeight / 1.5) + 15 }} showsVerticalScrollIndicator={false}> {getEventsForDay(selectedDate).map((event, index) => { const isExpanded = expandedEventIndexes.includes(index); return ( <TouchableOpacity onPress={() => toggleView(index)} key={index}> <Card style={styles.eventItem}> <View> <Text style={styles.eventItemTitle}>{event.title}</Text> {/* 根据当前事件的展开状态控制详情显示 */} <Text style={{ display: isExpanded ? "flex" : "none", color: "white", marginTop: 5 }}>{event.details}</Text> </View> {/* 根据当前事件的展开状态切换图标 */} {isExpanded ? ( <Ionicons name="chevron-up" color={Colors.primary} size={25} /> ) : ( <Ionicons name="chevron-down" color={Colors.primary} size={25} /> )} </Card> </TouchableOpacity> ); })} </ScrollView>
可选优化:用事件唯一ID代替索引
如果你的事件列表可能出现顺序变化(比如新增/删除事件),建议给每个事件添加唯一id字段,用ID代替索引来维护状态,避免索引错位:
// 给events数组添加唯一id const events = [ { id: 1, title: 'Maths Exam', date: '2023-04-17', time_start: "HH:MM", time_end: "HH:MM", duration: "HH:MM", teacher: "Ms. Sonila", details: "Lorem Ipsum Dolor Sit amet" }, { id: 2, title: 'English Quiz', date: '2023-04-17', time_start: "HH:MM", time_end: "HH:MM", duration: "HH:MM", teacher: "Ms. Morena", details: "Lorem Ipsum Dolor Sit amet" }, // 其余事件同理 ]; // 状态和切换函数改为基于ID const [expandedEventIds, setExpandedEventIds] = useState([]); const toggleView = (eventId) => { setExpandedEventIds(prevState => { if (prevState.includes(eventId)) { return prevState.filter(id => id !== eventId); } else { return [...prevState, eventId]; } }); }; // 渲染时判断逻辑 const isExpanded = expandedEventIds.includes(event.id); // onPress={() => toggleView(event.id)}
效果展示
点击前状态:
点击单个事件后的状态(仅该事件展开):
内容的提问来源于stack exchange,提问作者David Guri
相关产品推荐
相关产品推荐

