4

I am using Formik to create a reminder form that store some information, including date and time. And I've encountered a problem while using DateTimePicker from react-native-modal-datetime-picker in my form.

My main goal is when a user press a Date or Time input, DateTimePicker will be shown. After user choose the time, DateTimePicker will pass that value to the input and display that input onto screen. And when user press 'Submit' button, log console will print out the values props of Formik

Here is my code:

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>
         )
    }

}

When I ran this code, date and time input did not show the value I chose in DateTimePikcker before, and when I submit form date and time property in values props got null. Then I tried to fix the input's attribute:

 <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>

In this time the input did show value I chose from DateTimePicker but when I submit form the date property still return to null. The problem is that I don't know how to change the property in the values props of Formik when user chooses date in DateTimePicker. Can you guy help me to figure it out?

And one more problem is that handleSubmit props does not work in here. I try to put the console.log() in onSubmit attribute (you can see in my code above) but it's not working.

  • `setState` is [async](https://reactjs.org/docs/state-and-lifecycle.html#state-updates-may-be-asynchronous), `console.log` immediately after is meaningless - it can be logged from `render` or viewed from React DevTools (and it's similar for [hooks](https://stackoverflow.com/a/58877875/1176601)) – Aprillion Feb 15 '20 at 09:21

2 Answers2

11

Below is an example. Notice the use of Formik's 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>
  );
}
Peter Pompeii
  • 1,415
  • 1
  • 14
  • 16
0

I made an example for you. Please refer to this and fill out the code.

Example Link

import React, { Component } from "react";
import { Button, View,TextInput } from "react-native";
import DateTimePicker from "react-native-modal-datetime-picker";

let date_pick;
export default class DateTimePickerTester extends Component {
  constructor(props) {
    super(props);
    this.state = {
      isDateTimePickerVisible: false,
      reminder:{
        date: "8/24/2009"
      }
    };
  }

  showDateTimePicker = () => {
    date_pick = new Date(this.state.reminder.date);
    this.setState({ isDateTimePickerVisible: true });
  };

  hideDateTimePicker = () => {
    this.setState({ isDateTimePickerVisible: false });
  };

  handleDatePicked = date => {
    console.log("A date has been picked: ", date);
    this.hideDateTimePicker();
  };

  render() {
    return (
      <View style={{flex:1,justifyContent:"center",alignItems:"center"}}>
        <Button title="Show DatePicker" onPress={this.showDateTimePicker} />
        <DateTimePicker
          isVisible={this.state.isDateTimePickerVisible}
          onConfirm={this.handleDatePicked}
          onCancel={this.hideDateTimePicker}
          date={date_pick}
        />
         <TextInput value = {this.state.reminder.date} style={{width:"80%",height:20,borderColor:"red",borderWidth:1}} />
      </View>
    );
  }
}
hong developer
  • 13,291
  • 4
  • 38
  • 68