2

我有一个带有用于输入数据的表单的 React Native 应用程序。其中一个字段是 DateTime 值,但它是可选的。换句话说,用户可以根据需要选择一个日期,但如果该字段不相关,则可以将其留空/空。

但是,当我将 null 分配给 DateTimePicker 的日期属性时,我得到一个异常,即 null 不是对象。如果他们愿意,如何允许用户选择一个日期,但如果他们不希望该字段中的日期,则将其保留为“null”。

     <DateTimePicker
      isVisible={isDatePickerVisible}
      mode={mode}
      onConfirm={handleConfirm}
      onCancel={hideDatePicker}
      date={selectedDate}
      onBlur={onBlur}
    />

有没有我失踪的财产?我可以使用其他组件来完成此操作吗?

4

2 回答 2

2

请注意

请注意,此库目前公开了 iOS 上的 UIDatePicker 和 Android 上的 DatePickerDialog + TimePickerDialog 以及 Windows 上的 CalendarDatePicker +TimePicker 的功能。

这些本机类仅提供有限的配置,而作为开发人员,您可能需要许多可能的选项。因此,如果支持的原生视图不支持您的要求,该库将无法实现您的要求。当您打开功能请求的问题时,请记录是否(或如何)可以使用上述本机视图实现该功能。如果这些视图不支持您的需求,则此类功能请求将被视为不可操作而关闭。

react-native-datetimepicker文档中提供的那样。

您正在使用的date道具就是其中之一。对于 iOS,它公开了一个UIDatePicker字段,即

日期选择器将显示的初始日期。默认为当前日期,但您可以设置自定义值。此属性等效于以编程方式设置日期属性。

但是,如react-native-datetimepicker文档中所述,它的使用是有限的。我们需要使用的正确道具value

定义组件中使用的日期或时间值。

这是必填栏。我们不能取消它。总会有一些默认值需要在初始时明确设置。

但是,您想要实现的目标可以以不同的方式完成。您需要在表单状态下自己处理表单值。因此,

const [date, setDate] = useState()

表单中的状态date最初是未定义的。你的value道具DateTimePicker不是。

DateTimePicker得到onConfirmMethod一个. 如果被触发,请将您的date状态设置为value传递给的道具onConfirmMethod,如下所示

const onConfirm = (selectedDate) => {
    setDate(selectedDate)
}

<DateTimePicker
      isVisible={isDatePickerVisible}
      mode={mode}
      onConfirm={onConfirm}
      onCancel={hideDatePicker}
      value={date}
      onBlur={onBlur}
/>
}

通常您希望用户允许之后删除该字段。您需要自己实现此功能,因为value无法取消设置。如果所选date内容在某种 InputField 中可视化,则可以轻松完成。

然后,您的表单数据与您的DateTimePicker价值道具分离。恐怕没有其他办法,至少有这个库。

于 2022-02-22T08:18:38.893 回答
0

感谢@david-scholz 对 react-native-datetimepicker 库的深入了解以及对 null 支持的缺乏。话虽如此,他的回答并未提供所要求的功能。

我设法使用包含 react-native-modal-datetimepicker 库的自定义组件来实现它。基本思想是仅在用户想要选择日期时使用选择器。

要做到这一点:

  1. 文本用于显示当前值或“未选择日期”。
  2. 当用户单击文本时,将显示日期时间选择器以让他们选择日期
  3. 如果用户想要清除日期并返回 null,则可以单击一个按钮

注意:这旨在与 Formik 一起使用(在我的用例中),因此传回的日期/时间值采用字符串格式(与 Formik 一起使用效果更好)。

这是代码,以防任何人都可以使用它。它应该被视为 MIT 许可证。

import React, { useState } from 'react';
import { Text, View, StyleSheet, TouchableOpacity } from 'react-native';
import DateTimePickerModal from 'react-native-modal-datetime-picker';
import moment from 'moment';

const isNullOrWhitespace = ( input ) => {
  return !input || !input.trim();
}

export default function NullableDatePicker (props) {
    const {value, onChange, onBlur} = props;
    const [isDatePickerVisible, setDatePickerVisibility] = useState(false);
    const [selectedDate, setSelectedDate] = useState(isNullOrWhitespace(value) ?  new Date() : new Date(value));
    const [hasDate, setHasDate] = useState(isNullOrWhitespace(value) ? false : true);

    const showDatePicker = () => {
      setDatePickerVisibility(true);
    };
  
    const hideDatePicker = () => {
      setDatePickerVisibility(false);
    };
  
    const handleConfirm = date => {
      hideDatePicker();
      setHasDate(true);
      setSelectedDate(new Date(date));  
      onChange(valueToString(date));
    };
  
    const valueToString = selectedDate => {
        return moment(selectedDate).format('YYYY-MM-DD');
    }

    const clearDate = () => {
        setHasDate(false);
        onChange('');
    }
  
    return (
      <View>
        <View style={styles.fixToText}>
        <Text style={styles.dateText} onPress={showDatePicker}>{hasDate ? valueToString(selectedDate) : 'No Date Selected'}</Text>
        <Text>   </Text>
        <TouchableOpacity 
            title="Clear"
            onPress={() => clearDate()}
            disabled={!hasDate}
            style={styles.button}
        >
           <Text>Clear</Text> 
        </TouchableOpacity>
        </View>
        <DateTimePickerModal
          isVisible={isDatePickerVisible}
          mode='date'
          onConfirm={handleConfirm}
          onCancel={hideDatePicker}
          date={selectedDate}
          onBlur={onBlur}
        />
      </View>
    );  
  }
  const styles = StyleSheet.create(
      {
        fixToText: {
            flexDirection: 'row'
        },
        button: {
            alignItems: "center",
            backgroundColor: "lightblue",
            padding: 5,
            height: 30,
            width: 50
        },
        dateText:{
            height: 30,
            textAlignVertical: 'center'
        }
      }
  )
于 2022-02-23T19:20:00.640 回答