React Native:FlatList与DatePicker创建时间列表仅显示单条问题求助
解决FlatList仅显示单条时间记录的问题
我来帮你搞定这个问题!问题的核心是你每次选择时间时都直接替换了timeSlots数组,而不是往已有的列表里追加新条目,再加上Add按钮没有绑定添加逻辑,导致旧记录总是被覆盖。下面是具体的修复方案:
问题分析
- 在
setAppointmentTime和showTime方法中,你用timeSlots: [{ time: textAppointmentTime }]直接覆盖了原数组,这会导致每次选择新时间时,旧的记录被完全替换。 - 当前的"Add Appointment"按钮没有绑定任何事件,无法手动触发添加操作,不符合常规的用户操作流程。
修复后的完整代码
import React, { Component } from 'react'; import { View, Text, StyleSheet, TouchableOpacity, ScrollView, FlatList, Platform } from 'react-native'; import DatePicker from '@react-native-community/datetimepicker'; import Feather from 'react-native-vector-icons/Feather'; import moment from 'moment'; export default class FrCreateScreen extends Component { constructor(props) { super(props); this.state = { // Time selection state appointmentTime: new Date(moment()), modeAppointmentTime: 'time', showAppointmentTime: false, textAppointmentTime: moment().format('h:mm a').toString(), // Time slots list timeSlots: [], } } // Update selected time without modifying the slots list setAppointmentTime = (event, selectedTime) => { const appointmentTime = selectedTime || this.state.appointmentTime; const textAppointmentTime = moment(appointmentTime).format('h:mm a').toString(); this.setState({ showAppointmentTime: Platform.OS === 'ios' ? true : false, appointmentTime, textAppointmentTime, }); } showTime = (mode) => { this.setState({ showAppointmentTime: true, modeAppointmentTime: mode, }); } timePicker = () => { this.showTime('time'); } // Add selected time to slots list (with optional duplicate check) addTimeSlot = () => { const { textAppointmentTime, timeSlots } = this.state; // Optional: Prevent duplicate entries const isDuplicate = timeSlots.some(slot => slot.time === textAppointmentTime); if (isDuplicate) { alert('This time slot already exists!'); return; } this.setState(prevState => ({ timeSlots: [...prevState.timeSlots, { time: textAppointmentTime, id: Date.now().toString() }], })); } // Remove a specific time slot from the list removeTimeSlot = (id) => { this.setState(prevState => ({ timeSlots: prevState.timeSlots.filter(slot => slot.id !== id), })); } getAppointmentTimePage() { const { appointmentTime, showAppointmentTime, modeAppointmentTime, textAppointmentTime } = this.state; return ( <View> <Text style={[styles.title, { marginTop: 20 }]}>Select Appointment Time:</Text> <View style={styles.container}> <TouchableOpacity onPress={this.timePicker}> <Text style={styles.textDate}> {textAppointmentTime} </Text> </TouchableOpacity> {showAppointmentTime && ( <DatePicker value={appointmentTime} mode={modeAppointmentTime} onChange={this.setAppointmentTime} minimumDate={new Date(moment())} /> )} </View> {/* Bind add function to the button */} <TouchableOpacity style={styles.addContainer} onPress={this.addTimeSlot}> <Text style={styles.addText}>Add Appointment</Text> </TouchableOpacity> </View> ); } render() { return ( <ScrollView> {this.getAppointmentTimePage()} <View style={styles.row}> <FlatList data={this.state.timeSlots} keyExtractor={(item) => item.id} // Use unique ID instead of time (prevents issues with duplicates) renderItem={({ item }) => ( <View style={styles.slotItem}> <Text style={styles.textTime}>{item.time}</Text> <TouchableOpacity onPress={() => this.removeTimeSlot(item.id)}> <Feather name="trash" style={styles.icon} /> </TouchableOpacity> </View> )} /> </View> </ScrollView> ); }; }; // Placeholder styles (adjust according to your design) const styles = StyleSheet.create({ title: { fontSize: 16, fontWeight: 'bold', marginLeft: 15, }, container: { flexDirection: 'row', alignItems: 'center', marginHorizontal: 15, padding: 10, borderBottomWidth: 1, borderBottomColor: '#eee', }, textDate: { fontSize: 16, }, addContainer: { backgroundColor: '#007AFF', padding: 12, margin: 15, borderRadius: 8, alignItems: 'center', }, addText: { color: 'white', fontSize: 16, fontWeight: '500', }, row: { marginHorizontal: 15, marginTop: 20, }, slotItem: { flexDirection: 'row', justifyContent: 'space-between', alignItems: 'center', paddingVertical: 10, borderBottomWidth: 1, borderBottomColor: '#eee', }, textTime: { fontSize: 16, }, icon: { fontSize: 20, color: '#FF3B30', }, });
关键修改说明
分离时间选择和列表添加逻辑:
setAppointmentTime现在只负责更新当前选中的时间,不再直接修改timeSlots数组。- 添加了
addTimeSlot方法,点击"Add Appointment"按钮时才会把当前选中的时间追加到列表中。
避免数组覆盖:
使用扩展运算符(...prevState.timeSlots)复制原数组,再追加新条目:timeSlots: [...prevState.timeSlots, { time: textAppointmentTime, id: Date.now().toString() }]添加去重逻辑(可选):
通过some方法检查列表中是否已有相同时间,避免重复添加。实现删除功能:
- 给每个时间条目添加了唯一
id(用Date.now()生成),确保keyExtractor的唯一性。 - 添加
removeTimeSlot方法,通过过滤数组删除指定条目。
- 给每个时间条目添加了唯一
优化按钮绑定:
给"Add Appointment"按钮绑定了addTimeSlot方法,让用户可以手动控制添加时机。
这样修改后,你就可以多次选择时间并添加到FlatList中,旧记录不会被替换,还能删除不需要的时间条目啦!
内容的提问来源于stack exchange,提问作者Beep Boop
相关产品推荐
相关产品推荐

