Как использовать @ response-native-community/datetimepicker с формой React Hook?
Я пытаюсь сделать средство выбора даты, которое появляется при нажатии на поле со значком и текущей датой в строковом формате.
Я использую React Native, React Hook Form и @response-native-community/datetimepicker.
Случайно я нашел там интересный ответ на несвязанный вопрос: /questions/24761706/reaktivnaya-oshibka-znachenie-dlya-datyi-ne-mozhet-byit-preobrazovano-iz-stroki-v-dvojnuyu/55074483#55074483
Я реализовал это так:
const MyComponent = () => {
const { userData } = useContext(UserDataContext)
const [isPickerOpen, setIsPickerOpen] = useState(false)
const parsedBirthday = (userData && userData.birthday && userData.birthday.toDate()) || new Date()
const [birthday, setBirthday] = useState(parsedBirthday)
// Validation schema
const schema = yup.object({
birthday: yup.date(),
})
const { control, handleSubmit, errors } = useForm({resolver: yupResolver(schema)})
const onSubmit = async (data: any) => {
console.log(data)
}
const datePickerHandler = (selectedDate: Date) => {
const currentDate = selectedDate || birthday
if (Platform.OS === 'android') setIsPickerOpen(false)
setBirthday(currentDate)
}
const showDatePicker = () => {
setIsPickerOpen(true)
}
return (
<View style={styles.fieldContainer}>
<Text style={styles.helper}>Birthday</Text>
<TouchableHighlight activeOpacity={0.6} underlayColor="#DDDDDD" onPress={showDatePicker} style={styles.birthday}>
<>
<Icon name="calendar-edit" size={32} color={colors.black} />
<Controller
control={control}
render={({ onChange, onBlur, value }) => (
<TextInput
style={styles.birthdayText}
value={birthday.toLocaleDateString()}
editable={false}
pointerEvents="none"
onTouchStart={() => showDatePicker()}
/>
)}
name="birthdayString"
defaultValue={birthday.toLocaleDateString() || new Date().toLocaleDateString()}
/>
</>
</TouchableHighlight>
{/* Date picker */}
{isPickerOpen && (
<Controller
control={control}
render={({ onChange, onBlur, value }) => (
<>
<View>
<DateTimePicker
minimumDate={new Date(1901, 0, 1)}
maximumDate={new Date()}
value={value}
mode="date"
display="default"
onChange={(event, value) => {
datePickerHandler(value)
}}
/>
</View>
</>
)}
name="birthday"
defaultValue={birthday}
/>
)}
<Text style={styles.errorText}>{errors?.birthday}</Text>
</View>
)
Это немного сложно из-за того, что сборщик отключается при отправке значений. Затем нам понадобится компонент TextInput для хранения значения.
Интересно, есть ли лучший подход. У меня есть небольшие опасения:
- Я конвертирую строку в дату, затем в строку, затем мне нужно будет преобразовать ее обратно в дату при отправке... На самом деле.toLocaleDateString сделает отправку очень сложной. Это может быть проблемой для интернационализации.
- onTouchStart не работает с мышью, только с сенсорными устройствами. Это может быть проблема с Chromebook.
1 ответ
Чтобы использовать@react-native-community/datetimepicker
с React Hook Form вы можете сделать это следующим образом:
- Создайте пользовательский компонент, который интегрирует средство выбора даты с вашей формой.
const DatePicker = ({ control, name, value, onChange }) => {
return (
<Controller
control={control}
name={name}
defaultValue={value}
render={({ field: { onChange, value } }) => (
<DateTimePicker
value={value || new Date()} // Provide a default value if value is empty
mode="date" // You can use "time" or "datetime" for different modes
is24Hour={true}
display="default"
onChange={(event, selectedDate) => {
onChange(selectedDate);
}}
/>
)}
/>
);
};
- Теперь вы можете использовать компонент DatePicker в своей форме. Убедитесь, что вы инициализировали свою форму с помощью useForm.
const MyForm = () => {
const {
control,
handleSubmit,
formState: { errors },
} = useForm();
const [selectedDate, setSelectedDate] = useState(null);
const onSubmit = (data) => {
// Handle form submission with the selectedDate and other form data
console.log(data);
};
return (
<View>
<Text>Select a Date:</Text>
<DatePicker control={control} name="date" value={selectedDate} onChange={setSelectedDate} />
<Button title="Submit" onPress={handleSubmit(onSubmit)} />
</View>
);
};
export default MyForm;