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

React Native:FlatList与DatePicker创建时间列表仅显示单条问题求助

解决FlatList仅显示单条时间记录的问题

我来帮你搞定这个问题!问题的核心是你每次选择时间时都直接替换了timeSlots数组,而不是往已有的列表里追加新条目,再加上Add按钮没有绑定添加逻辑,导致旧记录总是被覆盖。下面是具体的修复方案:

问题分析

  1. 在setAppointmentTime和showTime方法中,你用timeSlots: [{ time: textAppointmentTime }]直接覆盖了原数组,这会导致每次选择新时间时,旧的记录被完全替换。
  2. 当前的"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',
  },
});

关键修改说明

  1. 分离时间选择和列表添加逻辑:

    • setAppointmentTime现在只负责更新当前选中的时间,不再直接修改timeSlots数组。
    • 添加了addTimeSlot方法,点击"Add Appointment"按钮时才会把当前选中的时间追加到列表中。
  2. 避免数组覆盖:
    使用扩展运算符(...prevState.timeSlots)复制原数组,再追加新条目:

    timeSlots: [...prevState.timeSlots, { time: textAppointmentTime, id: Date.now().toString() }]
    
  3. 添加去重逻辑(可选):
    通过some方法检查列表中是否已有相同时间,避免重复添加。

  4. 实现删除功能:

    • 给每个时间条目添加了唯一id(用Date.now()生成),确保keyExtractor的唯一性。
    • 添加removeTimeSlot方法,通过过滤数组删除指定条目。
  5. 优化按钮绑定:
    给"Add Appointment"按钮绑定了addTimeSlot方法,让用户可以手动控制添加时机。

这样修改后,你就可以多次选择时间并添加到FlatList中,旧记录不会被替换,还能删除不需要的时间条目啦!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 09:17:53