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

react-native-paper-dates日期输入自动格式化及键盘问题求助

react-native-paper-dates日期输入格式化问题

问题现象

  • 日期输入无法自动插入斜杠(/),且虚拟键盘无斜杠按键,无法手动输入MM/DD/YYYY格式日期
  • 仅输入满10位数字时,才会被自动格式化为MM/DD/YYYY样式(例如输入1234567891会转换为01/14/7892)

相关代码

import React, {Component} from 'react';
import {View, StyleSheet, Text} from 'react-native';
import {Button, Provider as PaperProvider} from 'react-native-paper';
import 'intl';
import 'intl/locale-data/jsonp/en';
import dayjs from 'dayjs';
import {DatePickerModal, TimePickerModal} from 'react-native-paper-dates';

import NewRow from './NewRow';

import {fontSize} from '../resources/fontSize';
import {colors} from '../resources/colors';
import {theme} from '../resources/theme';
import moment from 'moment';

interface Time {
  hours: string;
  minutes: string;
}

interface State {
  isDatePickerVisible: boolean;
  date: Date | null;
  isTimePickerVisible: boolean;
  time: Time | null;
}

interface Props {
  title: string;
  time: string;
  onDateSelected: (date: Date) => void;
  onTimeSelected: (date: Time) => void;
  initialDate?: string;
  initialTime?: string;
  mode?: 'date' | 'time' | 'datetime' | undefined;
  dateFormat?: string;
  edit?: any;
  haveEnd?: boolean;
  haveStart?: boolean;
}

/**
 * Date picker component based on `react-native-paper-dates`
 */
class PickDateAndTime extends Component<Props, State> {
  constructor(props: any) {
    super(props);

    const date =
      props.initialDate !== null ? new Date(props.initialDate) : null;

    const time =
      props.initialTime !== null && props.initialTime !== undefined
        ? {
            hours: props.initialTime.split(':')[0],
            minutes: props.initialTime.split(':')[1],
          }
        : null;

    this.state = {
      isDatePickerVisible: false,
      date,
      isTimePickerVisible: false,
      time,
    };
  }

  toggleDatePicker = (): void => {
    this.setState(preState => ({
      isDatePickerVisible: !preState.isDatePickerVisible,
    }));
  };

  toggleTimePicker = (): void => {
    this.setState(preState => ({
      isTimePickerVisible: !preState.isTimePickerVisible,
    }));
  };

  handleTimePicked = (time: any): void => {
    const newTime = time ?? new Date().getTime();

    this.setState({time: newTime, isTimePickerVisible: false});

    this.props.onTimeSelected(newTime);
  };

  handleDatePicked = (date: any): void => {
    const newDate = date.date ?? new Date();

    this.setState({date: newDate, isDatePickerVisible: false});

    this.props.onDateSelected(newDate);
  };

  render(): React.ReactElement {
    const {date, isDatePickerVisible, time, isTimePickerVisible} = this.state;
    const {dateFormat} = this.props;

    const displayText =
      date != null
        ? dateFormat !== ''
          ? dayjs(date).format(dateFormat)
          : date
        : '';
    const displayTime = time != null ? moment(time as any).format('HH:mm') : '';

    return (
      <PaperProvider theme={{...theme}}>
        <DatePickerModal
          locale="en"
          mode={'single'}
          label={
            this.props.edit === true ? 'Izmenite datum' : 'Izaberite datum'
          }
          animationType={'fade'}
          saveLabel="Potvrdi"
          visible={isDatePickerVisible}
          onDismiss={this.toggleDatePicker}
          date={date ?? new Date()}
          onConfirm={this.handleDatePicked}
          startYear={1950}
          validRange={{
            endDate: this.props.haveEnd ? new Date() : undefined,
            startDate: this.props.haveStart ? new Date() : undefined,
          }}
        />
        <TimePickerModal
          visible={isTimePickerVisible}
          onDismiss={this.toggleTimePicker}
          onConfirm={this.handleTimePicked}
          label={
            this.props.edit === true ? 'Izmenite vreme' : 'Izaberite vreme'
          }
          uppercase={true}
          cancelLabel="Otkaži"
          confirmLabel="Potvrdi"
          animationType="fade"
          inputFontSize={33}
          locale="en"
        />
        <NewRow height={10} />
        <View
          style={{
            flexDirection: 'row',
            width: '100%',
            justifyContent: 'space-between',
          }}>
          <View style={{width: '45%', marginLeft: 10}}>
            {this.props.edit === true ? (
              <Button
                mode={'outlined'}
                style={[styles.buttonStyle]}
                labelStyle={styles.labelStyle}
                onPress={this.toggleDatePicker}>
                {'Izmeni datum'}
              </Button>
            ) : (
              <Button
                mode={'outlined'}
                style={[styles.buttonStyle]}
                labelStyle={styles.labelStyle}
                onPress={this.toggleDatePicker}>
                {'Dodaj datum'}
              </Button>
            )}
          </View>
          <View style={{width: '45%', marginRight: 10}}>
            {this.props.edit === true ? (
              <Button
                mode={'outlined'}
                style={[styles.buttonStyle]}
                labelStyle={styles.labelStyle}
                onPress={this.toggleTimePicker}>
                {'Izmeni vreme'}
              </Button>
            ) : (
              <Button
                mode={'outlined'}
                style={[styles.buttonStyle]}
                labelStyle={styles.labelStyle}
                onPress={this.toggleTimePicker}>
                {'Dodaj vreme'}
              </Button>
            )}
          </View>
        </View>
        <NewRow height={10} />
        {displayText !== '' && (
          <View style={{flexDirection: 'row', marginLeft: 20}}>
            <Text
              style={{
                color: colors.blue,
                fontSize: fontSize.font16,
                fontWeight: 'normal',
              }}>
              {'Datum: '}
            </Text>
            <Text
              style={{
                color: colors.blue,
                fontSize: fontSize.font16,
                fontWeight: 'normal',
              }}>
              {displayText.toString()}
            </Text>
          </View>
        )}
        {displayTime !== '' && (
          <View style={{flexDirection: 'row', marginLeft: 20}}>
            <Text
              style={{
                color: colors.blue,
                fontSize: fontSize.font16,
                fontWeight: 'normal',
              }}>
              {'Vreme: '}
            </Text>
            <Text
              style={{
                color: colors.blue,
                fontSize: fontSize.font16,
                fontWeight: 'normal',
              }}>
              {displayTime}
            </Text>
          </View>
        )}
      </PaperProvider>
    );
  }
}

const styles = StyleSheet.create({
  buttonStyle: {
    alignSelf: 'center',
    width: '100%',
    borderColor: colors.blue,
  },
  labelStyle: {
    color: colors.blue,
    fontSize: fontSize.font12,
    fontWeight: '700',
  },
});

export default PickDateAndTime;

解决方案

1. 启用组件自带格式化

给DatePickerModal添加format属性指定目标格式,同时设置textInputMode触发适配的日期键盘:

<DatePickerModal
  // 保留原有属性
  format="MM/DD/YYYY"
  textInputMode="datetime"
/>

2. 自定义实时格式化逻辑

如果组件自带功能不生效,手动监听输入并插入斜杠:

// 扩展State
interface State {
  // 原有状态
  inputDate: string;
}

// 构造函数初始化
constructor(props: any) {
  super(props);
  // 原有代码
  this.state = {
    // 原有状态
    inputDate: '',
  };
}

// 格式化输入的工具函数
const formatDateInput = (text: string) => {
  const cleaned = text.replace(/\D/g, '');
  let formatted = '';
  if (cleaned.length >= 2) formatted += cleaned.substring(0, 2) + '/';
  if (cleaned.length >= 4) formatted += cleaned.substring(2, 4) + '/';
  formatted += cleaned.length > 4 ? cleaned.substring(4, 8) : cleaned.substring(2);
  return formatted;
};

// 更新DatePickerModal配置
<DatePickerModal
  // 保留原有属性
  onChangeText={(text) => {
    const formatted = formatDateInput(text);
    this.setState({ inputDate: formatted });
    // 输入完整时同步日期状态
    if (formatted.length === 10) {
      const [month, day, year] = formatted.split('/');
      this.setState({ date: new Date(`${year}-${month}-${day}`) });
    }
  }}
  value={this.state.inputDate}
/>

3. 调整键盘类型

将键盘类型改为default,让用户可以手动输入斜杠:

<DatePickerModal
  // 保留原有属性
  keyboardType="default"
/>

4. 检查版本兼容性

更新到最新版react-native-paper-dates,修复旧版本的格式化bug:

npm update react-native-paper-dates
# 或
yarn upgrade react-native-paper-dates

内容的提问来源于stack exchange,提问作者Kristina Dzelebdzic

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.17 03:48:11