首页 > 解决方案 > 用 Formik 处理 React Native 中 DateTimePicker 的值

问题描述

我正在使用 Formik 创建一个提醒表单来存储一些信息,包括日期和时间。我在表单中使用DateTimePickerfrom时遇到了问题。react-native-modal-datetime-picker

我的主要目标是当用户按下日期或时间输入时,DateTimePicker将显示。用户选择时间后, DateTimePicker将该值传递给输入并将该输入显示在屏幕上。当用户按下“提交”按钮时,日志控制台将打印valuesFormik

这是我的代码:

import React from 'react'
import {View, TouchableOpacity} from 'react-native'
import {Button, Input} from 'react-native-elements'
import ModalDropdown from 'react-native-modal-dropdown'
import DateTimePicker from 'react-native-modal-datetime-picker'
import {Formik} from 'formik'
import * as yup from 'yup'

export default class ReminderForm extends React.Component{
    constructor(props){
        super(props);
        this.state = {
           isDatePickerVisible: false,
           isTimePickerVisible: false,
           reminder: {
               date: '',
               time: '',
               //...more properties go here
           }
        }
    }
    showDatePicker = () => {//show the picker for Date input
        this.setState({ isDatePickerVisible: true });
    };

    hideDatePicker = () => {
        this.setState({ isDatePickerVisible: false });
    };
    handleDatePicked = date => {
        let newDate = new Date(date).toLocaleDateString();
        this.setState(prevState=> ({
            ...prevState,
            isDatePickerVisible: !prevState.isDatePickerVisible,
            reminder: {
                ...prevState.reminder,
                date: newDate
            }
        }));
        console.log(this.state);
    };
    showTimePicker = () => {//show the picker for time input
        this.setState({ isTimePickerVisible: true });
    };

    hideTimePicker = () => {
        this.setState({ isTimePickerVisible: false });
    };
    handleTimePicked = time => {
        let newTime = new Date(time).toLocaleTimeString();
        this.setState(prevState=> ({
            ...prevState,
            isTimePickerVisible: !prevState.isTimePickerVisible,
            reminder: {
                ...prevState.reminder,
                time: newTime
            }
        }))
        console.log(this.state)
    };
    render(){
        return(
            <View style = {{flex:1}}>
                 <Formik initialValues = {this.state.reminder}
                        onSubmit={()=> console.log('Submitted')}
                       >
                     {
                         ({values,handleChange,errors,setFieldTouched,touched,isValid,handleSubmit})=>(
                            <View style ={{flex:1, justifyContent:'space-around'}}>
                                <TouchableOpacity style ={{flex:1, marginTop: 10, marginBottom:10, backgroundColor:null}}
                                                  onPress={this.showDatePicker}>
                                    <Input value = {values.date}  inputContainerStyle={{height: '60%'}} onChangeText={handleChange('date')}
                                           onBlur={()=>setFieldTouched('date')} label = "Date" labelStyle = {{fontSize: 15}}/>
                                </TouchableOpacity>  
                                <DateTimePicker mode="date" isVisible={this.state.isDatePickerVisible} 
                                                 onConfirm={this.handleDatePicked} onCancel={this.hideDatePicker}/>
                                <TouchableOpacity style ={{flex:1, marginTop: 10, marginBottom:10, backgroundColor:null}}
                                                  onPress={this.showTimePicker}>
                                    <Input value = {values.time}  
                                           onChangeText={handleChange('time')} inputContainerStyle={{height: '60%'}}
                                           onBlur={()=>setFieldTouched('time')} label = "Time" labelStyle = {{fontSize: 15}}/>
                                </TouchableOpacity>          
                                <DateTimePicker mode="time" isVisible={this.state.isTimePickerVisible} 
                                                 onConfirm={this.handleTimePicked} onCancel={this.hideTimePicker}/>

                             //..more inputs go here
                                 <Button containerStyle = {{flex:1, marginTop: 10, marginBottom:0}} TouchableComponent={TouchableOpacity}
                                        onPress={()=> console.log(values)}  title = "Submit" titleStyle = {{fontSize: 15}}/> 


                            </View> 
                         )
                     }
                 </Formik>
            </View>
         )
    }

}

当我运行此代码时,日期和时间输入没有显示我之前选择的值,并且当我在props中DateTimePikcker提交表单datetime属性时为空。values然后我尝试修复输入的属性:

 <TouchableOpacity style ={{flex:1, marginTop: 10, marginBottom:10, backgroundColor:null}}
                                                  onPress={this.showDatePicker}>
                                    <Input value = {this.state.reminder.date}  inputContainerStyle={{height: '60%'}} onChangeText={handleChange('date')}
                                           onBlur={()=>setFieldTouched('date')} label = "Date" labelStyle = {{fontSize: 15}}/>
                                </TouchableOpacity>

在这个时候,输入确实显示了我选择的值,DateTimePicker但是当我提交表单时,date属性仍然返回 null。问题是我不知道如何更改valuesFormik用户在DateTimePicker. 你能帮我弄清楚吗?

还有一个问题是handleSubmitprops 在这里不起作用。我尝试输入console.log()inonSubmit属性(您可以在上面的代码中看到),但它不起作用。

标签: reactjsreact-nativeformik

解决方案


下面是一个例子。注意 Formik 的setFieldValue的使用。

import React, { useState } from 'react';
import { Button, Text, View } from 'react-native';
import { Formik } from 'formik';
import DateTimePickerModal from 'react-native-modal-datetime-picker';
import moment from 'moment';

export default function Example() {
  return (
    <Formik initialValues={{ myDate: moment().format('YYYY-MM-DD') }} onSubmit={values => console.log(values)}>
      {({ handleSubmit, values, setFieldValue }) => (
        <MyForm values={values} setFieldValue={setFieldValue} handleSubmit={handleSubmit} />
      )}
    </Formik>
  );
}

export const MyForm = props => {
  const { handleSubmit, values, setFieldValue } = props;
  const [isDatePickerVisible, setDatePickerVisibility] = useState(false);

  const showDatePicker = () => {
    setDatePickerVisibility(true);
  };

  const hideDatePicker = () => {
    setDatePickerVisibility(false);
  };

  const handleConfirm = date => {
    setFieldValue('myDate', moment(date).format('YYYY-MM-DD'))
    hideDatePicker();
  };

  return (
    <View>
      <Text onPress={showDatePicker}>{moment(values.myDate).format('YYYY-MM-DD')}</Text>
      <DateTimePickerModal
        isVisible={isDatePickerVisible}
        mode="date"
        onConfirm={handleConfirm}
        onCancel={hideDatePicker}
        date={moment(values.myDate).toDate()}
      />
      <Button title="Submit" onPress={handleSubmit} />
    </View>
  );
}

推荐阅读