繁体   English   中英

MUI 时间选择器不在输入字段中显示格式化的时间值

[英]MUI Time picker doesn't show formatted time value in input field

我的主要目标是使用带有 yup 验证和 react-hook-form 的 MUI 时间选择器,但我面临的问题是,当我从时间选择器中选择时间时,文本字段中的值不会更新,如下所示。 主要问题图片

我为我的数据库使用了“TIME”类型,所以我需要对输入进行格式化。 但是,工作时间(结束时间)返回数据库中不接受的带有日期的时间。 差异显示在下面的控制台日志中。

day: "tuesday"
end_time: "Tue May 31 2022 05:27:00 GMT+0545 (Nepal Time)"
start_time: "05:29:00"
subject: "Account"
[[Prototype]]: Object

这是我的源代码:

import React, { useState, useEffect } from 'react'
import { Button, Box, Card, CardContent, TextField, Typography, CardHeader, Grid, MenuItem } from '@mui/material';
import { useNavigate, useParams } from 'react-router-dom';
import { useForm, Controller } from 'react-hook-form';
import { yupResolver } from '@hookform/resolvers/yup';
import * as Yup from 'yup';
import { AdapterDateFns } from '@mui/x-date-pickers/AdapterDateFns';
import { TimePicker, LocalizationProvider } from '@mui/x-date-pickers';
import { format, parseISO } from 'date-fns';
import TimeTableService from '../../../services/timetable.service';
import SubjectService from '../../../services/subject.service';

const TimetableForm = () => {
    const { id } = useParams();
    const validationSchema = Yup.object().shape({
        day: Yup.string().required("Day is required"),
        start_time: Yup.string().required("Start time is required"),
        end_time: Yup.string().required("End time is required"),
        subject: Yup.string().required("Subject is required"),
    });
    const {
        control,
        handleSubmit,
        setValue,
        formState: { errors }
    } = useForm({ resolver: yupResolver(validationSchema), mode: 'onChange' });
    const initialTimeTableState = {
        id: null,
        day: '',
        start_time: '',
        end_time: '',
        Subject: {},
    }
    const [currentTimeTable, setCurrentTimeTable] = useState(initialTimeTableState);
    const [subjects, setSubjects] = useState([]);
    const [editMode, setEditMode] = useState(false);
    const [loading, setLoading] = useState(false);
    const [message, setMessage] = useState("");
    const navigate = useNavigate();

    useEffect(() => {
        SubjectService.getAllSubjects().then(response => {
            setSubjects(response.data);
        })
        if (id) {
            TimeTableService.getTimeTable(id).then(response => {
                const timeTable = response.data;
                const fields = ['day', 'start_time', 'end_time'];
                fields.forEach(field => setValue(field, timeTable[field]));
                setValue('subject', timeTable.Subject.name);
                setCurrentTimeTable(timeTable);
                setEditMode(true);
            })
        }
    }, [id, setValue]);

    const onError = (errors, e) => console.log(errors, e);
    const onSubmit = (data) => {
        const start_time = data.start_time;
        // const start = format(start_time, "hh:mm a");
        console.log(start_time, data);
        // setMessage("");
        // setLoading(true);
        // if (editMode) {
        //     TimeTableService.updateTimeTable(id, data).then(() => {
        //         setLoading(false);
        //         navigate("/dashboard/timetable");
        //     }, (error) => {
        //         const resMessage = (error.response && error.response.data && error.response.data.message) || error.message || error.toString();
        //         setLoading(false);
        //         setMessage(resMessage);
        //     });
        // } else {
        //     TimeTableService.createTimeTable(data).then(() => {
        //         setLoading(false);
        //         navigate("/dashboard/timetable");
        //         window.location.reload();
        //     }, (error) => {
        //         const resMessage = (error.response && error.response.data && error.response.data.message) || error.message || error.toString();
        //         setLoading(false);
        //         setMessage(resMessage);
        //     });
        // }
    }

    const days = [
        {
            title: "Sunday",
            value: "sunday"
        },
        {
            title: "Monday",
            value: "monday"
        },
        {
            title: "Tuesday",
            value: "tuesday"
        },
        {
            title: "Wednesday",
            value: "wednesday"
        },
        {
            title: "Thursday",
            value: "thursday"
        },
        {
            title: "Friday",
            value: "friday"
        },
        {
            title: "Saturday",
            value: "saturday"
        }
    ];

    return (
        <Box sx={{ mt: 3 }}>
            <Card>
                <Box sx={{ minWidth: 1050 }}>
                    <CardHeader
                        title={id ? "Edit Time Table" : "Add Time Table"}
                    />
                    <CardContent>
                        {message && (<Typography variant='body2' color='error' >{message}</Typography>)}
                        <Grid container spacing={2}>
                            <Grid item md={4} xs={6}>
                                <LocalizationProvider dateAdapter={AdapterDateFns}>
                                    <Controller
                                        control={control}
                                        name="start_time"
                                        defaultValue={currentTimeTable.start_time || ""}
                                        render={({ field }) => (
                                            <TimePicker
                                                {...field}
                                                inputFormat="HH:mm:ss"
                                                mask='__:__:__'
                                                label="Start Time"
                                                onChange={(time) => {
                                                    const formattedTime = format(time, "HH:mm:ss");
                                                    field.onChange(formattedTime);
                                                }}
                                                renderInput={(params) => (
                                                    <TextField
                                                        {...params}
                                                        fullWidth
                                                        label="Start Time"
                                                        variant="outlined"
                                                        margin='dense'
                                                        color='dark'
                                                        size='small'
                                                        error={errors.start_time ? true : false}
                                                    />
                                                )}
                                            />
                                        )}
                                    />
                                </LocalizationProvider>
                                <Typography variant="body2" color="error">
                                    {errors.start_time?.message}
                                </Typography>
                            </Grid>
                            <Grid item md={4} xs={6}>
                                <LocalizationProvider dateAdapter={AdapterDateFns}>
                                    <Controller
                                        control={control}
                                        name="end_time"
                                        defaultValue={currentTimeTable.end_time || ""}
                                        render={({ field }) => (
                                            <TimePicker
                                                {...field}
                                                label="End Time"
                                                // onChange={(time) => field.onChange(time)}
                                                renderInput={(params) => (
                                                    <TextField
                                                        {...params}
                                                        fullWidth
                                                        label="End Time"
                                                        variant="outlined"
                                                        margin='dense'
                                                        color='dark'
                                                        size='small'
                                                        error={errors.end_time ? true : false}
                                                    />
                                                )}
                                            />
                                        )}
                                    />
                                </LocalizationProvider>
                                <Typography variant="body2" color="error">
                                    {errors.end_time?.message}
                                </Typography>
                            </Grid>
                            <Grid item md={4} xs={6}>
                                <Controller
                                    control={control}
                                    name='subject'
                                    defaultValue={currentTimeTable.Subject.name || ""}
                                    render={({ field }) => (
                                        <>
                                            <TextField
                                                {...field}
                                                select
                                                fullWidth
                                                label='Subject'
                                                variant='outlined'
                                                margin='dense'
                                                color='dark'
                                                size='small'
                                                error={errors.subject ? true : false}
                                            >
                                                {subjects.map(subject => (
                                                    <MenuItem key={subject.id} value={subject.name}>{subject.name}</MenuItem>
                                                ))}
                                            </TextField>
                                        </>
                                    )}
                                />
                                <Typography variant="body2" color="error">
                                    {errors.subject?.message}
                                </Typography>
                            </Grid>
                            <Grid item md={4} xs={6}>
                                <Controller
                                    control={control}
                                    name='day'
                                    defaultValue={currentTimeTable.day || ""}
                                    render={({ field }) => (
                                        <>
                                            <TextField
                                                {...field}
                                                select
                                                fullWidth
                                                label='Day'
                                                variant='outlined'
                                                margin='dense'
                                                color='dark'
                                                size='small'
                                                error={errors.day ? true : false}
                                            >
                                                {days.map(day => (
                                                    <MenuItem key={day.title} value={day.value}>{day.title}</MenuItem>
                                                ))}
                                            </TextField>
                                        </>
                                    )}
                                />
                                <Typography variant="body2" color="error">
                                    {errors.day?.message}
                                </Typography>
                            </Grid>
                        </Grid>
                        <Button
                            variant='outlined'
                            color={(loading) ? 'warning' : 'success'}
                            sx={{ my: 1.5 }}
                            disabled={(loading) ? true : false}
                            onClick={handleSubmit(onSubmit, onError)}>
                            {(loading) ? "Loading..." : "Submit"}
                        </Button>
                    </CardContent>
                </Box>
            </Card>
        </Box>
    )
}

export default TimetableForm

有没有什么办法解决这一问题? 谢谢。

注意: TimetableForm组件是使用 react 路由的<Outlet />渲染的。

编辑:这是 codeSandbox 链接: https ://codesandbox.io/s/gifted-roentgen-94bnpq

问题出在这行代码中:

onChange={(time) => {
          const formattedTime = format(time, "HH:mm:ss");
          field.onChange(formattedTime);
}}

这是因为format(time, "HH:mm:ss")返回一个String ,但时间选择器需要一个Date对象。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM