I have recently started studies in react native and am having difficulty with datetimepicker as DatePickerAndroid and TimePickerAndroid have been deprecated
In my Task view I'm importing the DateTimePickerInput component that I've broken down to make it more dynamic. In the task register it is working perfectly using the documentation assembly. But to update a task already registered, it does not update the input or save, accusing the following error:
(node:17560) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode).
Task view index:
import React, {useState, useEffect} from "react";
import {
View,
ScrollView,
Text,
Image,
TextInput,
KeyboardAvoidingView,
TouchableOpacity,
Switch,
Alert,
ActivityIndicator
} from "react-native";
import * as Network from 'expo-network';
//COMPONENTES
import Header from "../../components/Header";
import Footer from "../../components/Footer";
import styles from "./styles";
import DateTimeInput from "../../components/DateTimeInput";
import DateTimePickerInput from '../../components/DateTimePickerInput';
//ICONES
import typeIcons from "../../utils/typeIcons";
//API
import api from "../../services/api";
export default function Task({navigation}) {
const [id, setId] = useState();
const [done, setDone] = useState(false);
const [type, setType] = useState();
const [title, setTitle] = useState();
const [description, setDescription] = useState();
const [date, setDate] = useState();
const [hour, setHour] = useState();
const [macaddress, setMacaddress] = useState();
const [load, setLoad] = useState(true);
async function SaveTask() {
if (!title)
return Alert.alert('Defina o nome da tarefa!');
if (!description)
return Alert.alert('Defina a descrição da tarefa!');
if (!type)
return Alert.alert('Escolha um tipo para a tarefa!');
if (!date)
return Alert.alert('Escolha uma data para tarefa!');
if (!hour)
return Alert.alert('Escolha uma hora para tarefa!');
if (id) {
await api.put(`/task/${id}`, {
macaddress,
done,
type,
title,
description,
when: `${date}T${hour}.000`
}).then((response) => {
navigation.navigate('Home');
}).catch((error) => {
console.error(error);
});
} else {
await api.post('/task', {
macaddress,
type,
title,
description,
when: `${date}T${hour}.000`
}).then((response) => {
navigation.navigate('Home');
}).catch((error) => {
console.error(error);
});
}
}
async function LoadTask() {
await api.get(`/task/${id}`).then((response) => {
setLoad(true);
setDone(response.data.done);
setType(response.data.type);
setTitle(response.data.title);
setDescription(response.data.description);
setDate(response.data.when);
setHour(response.data.when);
}).catch((error) => {
console.error(error);
})
}
async function getMacAddress() {
//TODO: change to react-native-device-info
await Network.getMacAddressAsync().then(mac => {
setMacaddress(mac);
setLoad(false);
});
}
useEffect(() => {
getMacAddress();
if (navigation.state.params) {
setId(navigation.state.params.idTask);
LoadTask().then(() => setLoad(false));
}
}, [macaddress]);
return (
<KeyboardAvoidingView /*behavior='padding'*/ style={styles.container}>
<Header showBack={true} navigation={navigation}/>
{
load ?
<ActivityIndicator color='#EE6B26' size={50} style={{marginTop: 250}}/>
:
<ScrollView style={{width: '100%'}}>
<ScrollView horizontal={true} showsHorizontalScrollIndicator={false}
style={{marginVertical: 10}}>
{
typeIcons.map((icon, index) => (
icon !== null &&
<TouchableOpacity onPress={() => setType(index)}>
<Image key={index} source={icon}
style={[styles.imageIcon, type && type !== index && styles.typeIconInative]}/>
</TouchableOpacity>
))
}
</ScrollView>
<Text style={styles.label}>Título</Text>
<TextInput style={styles.input} maxLength={30} placeholder='Lembre-me de fazer...'
onChangeText={(text) => setTitle(text)} value={title}/>
<Text style={styles.label}>Detalhes</Text>
<TextInput style={styles.inputArea} maxLength={200} multiline={true}
placeholder='Detalhes da atividade que eu tenho que lembrar...'
onChangeText={(text) => setDescription(text)} value={description}/>
{/*
ANDROID e IOS:
Para os antigos DatePickerAndroid e TimePickerAndroid utilizar os seguintes inputs:
<DateTimeInput type={'date'} save={setDate}/>
<DateTimeInput type={'hour'} save={setHour}/>
*/}
<DateTimePickerInput type={'date'} save={setDate} dateWhen={date}/>
<DateTimePickerInput type={'hour'} save={setHour} hourWhen={hour}/>
{
id &&
<View style={styles.inLine}>
<View style={styles.inputInLine}>
<Switch onValueChange={() => setDone(!done)} value={done}
thumbColor={done ? '#EE6B26' : '#20295F'}/>
<Text style={styles.switchLabel}>Concluído</Text>
</View>
<TouchableOpacity>
<Text style={styles.removeLabel}>Excluir</Text>
</TouchableOpacity>
</View>
}
</ScrollView>
}
<Footer icon={'save'} onPress={SaveTask}/>
</KeyboardAvoidingView>
)
}
DateTimePickerInput component index for Android:
import React, {useEffect, useState} from "react";
import {TouchableOpacity, Image, TextInput, Platform, View, Alert} from "react-native";
import styles from "./styles";
import iconCalendar from '../../assets/calendar.png'
import iconClock from '../../assets/clock.png'
import {format, isPast} from "date-fns";
import RNDateTimePicker from "@react-native-community/datetimepicker";
export default function DateTimeInputAndroid({type, save, dateWhen, hourWhen}) {
const [dateNow, setDateNow] = useState(new Date());
const [mode, setMode] = useState('date');
const [show, setShow] = useState(false);
const [dateinput, setDateInput] = useState();
const [timeinput, setTimeInput] = useState();
const onChange = (event, selectedDate) => {
const currentDate = selectedDate || dateNow;
setShow(Platform.OS === 'ios');
setDateNow(currentDate);
if (event.nativeEvent.timestamp !== undefined) {
if (!event.nativeEvent.timestamp.toString().includes('T')) {
if (isPast(currentDate)) {
Alert.alert('Você não pode escolher uma data no passado!');
} else {
setDateInput(format(currentDate, 'dd/MM/yyyy'));
save(format(currentDate, 'yyyy-MM-dd'));
}
} else {
setTimeInput(format(currentDate, 'HH:mm'))
save(format(currentDate, 'HH:mm:ss'));
}
}
};
const showMode = (currentMode) => {
setShow(true);
setMode(currentMode);
};
const showDatepicker = () => {
showMode('date');
};
const showTimepicker = () => {
showMode('time');
};
// useEffect(() => {
// if (dateWhen) {
// setDateInput(format(new Date(dateWhen), 'dd/MM/yyyy'));
// // save(format(new Date(dateWhen), 'yyyy-MM-dd'));
// }
// if (hourWhen) {
// setTimeInput(format(new Date(hourWhen), 'HH:mm'));
// // save(format(new Date(hourWhen), 'HH:mm:ss'));
// }
// });
return (
<View>
<TouchableOpacity onPress={type === 'date' ? showDatepicker : showTimepicker}>
<TextInput style={styles.input}
placeholder={type === 'date' ? 'Clique aqui para definir a data...' : 'Clique aqui para definir a hora...'}
editable={false}
value={type === 'date' ? dateinput : timeinput}
/>
<Image style={styles.iconTextInput} source={type === 'date' ? iconCalendar : iconClock}/>
</TouchableOpacity>
{
show && (
<RNDateTimePicker
value={dateNow}
mode={mode}
is24Hour={true}
display="default"
onChange={onChange}
/>
)
}
</View>
)
};
Note: To better visualize the project, just access the following link: todo-mobile