MaterialUI Datepicker结合Dayjs、useFormik与Yup使用异常求助
Material UI Datepicker 搭配 Dayjs 遇到的问题
问题描述
- 首次选择日历日期时文本框会更新,但后续操作失效
- Yup验证首次触发表单字段时报错正常,但清空日期字段后验证不生效
代码示例
import "./styles.css"; import React, { useState } from "react"; import { TextField, Container, Typography, Stack, Button, Box } from "@mui/material"; import { Link } from "react-router-dom"; import { Helmet } from "react-helmet-async"; import { styled } from "@mui/material/styles"; import { AdapterDayjs } from "@mui/x-date-pickers/AdapterDayjs"; import { DatePicker } from "@mui/x-date-pickers/DatePicker"; import { DesktopDatePicker } from "@mui/x-date-pickers/DesktopDatePicker"; import TodayIcon from "@mui/icons-material/Today"; import moment from "moment"; import dayjs from "dayjs"; import { LocalizationProvider } from "@mui/x-date-pickers/LocalizationProvider"; import InputAdornment from "@mui/material/InputAdornment"; import Autocomplete from "react-google-autocomplete"; import { useFormik } from "formik"; import * as Yup from "yup"; // import useResponsive from "../../hooks/useResponsive"; export default function App() { // const navigate = useNavigate(); const validationSchema = Yup.object().shape({ firstName: Yup.string().required("First Name is required"), lastName: Yup.string() // .length(3, 'Last Name must be greater than 3 characters') .required("Last Name is required"), email: Yup.string() .email("Invalid email") .required("Please enter your email"), mobile: Yup.string() .length(10, "Mobile Number must be 10 digit") .required("Mobile Number is required"), dob: Yup.string().required("Dob is required"), passingYear: Yup.string().required("Passing out year is required"), location: Yup.string().required("Location is required"), occupation: Yup.string().required("Occupation is required"), address: Yup.string().required("Addres is required") }); const formik = useFormik({ initialValues: { firstName: "", lastName: "", email: "", mobile: "", dob: "", passingYear: "", location: "", address: "", occupation: "" }, validationSchema, onSubmit: (values) => { console.log(values); // navigate(`/verify-otp?email=${values.email}`, { replace: true }); } }); return ( <div className="App"> <form onSubmit={formik.handleSubmit}> <Stack direction={"column"} spacing={3}> <Box> <TextField sx={{ width: "100%" }} id="outlined-firstName-input" label="First Name" name="firstName" type={"text"} onChange={formik.handleChange} value={formik.values.firstName} onBlur={formik.handleBlur} autoComplete="off" /> {formik.touched.firstName && formik.errors.firstName && ( <p style={{ color: "red", marginTop: "5px", marginBottom: "-15px" }} > {formik.errors.firstName} </p> )} </Box> <Box> <TextField sx={{ width: "100%" }} id="outlined-lastName-input" label="Last Name" name="lastName" type={"text"} onChange={formik.handleChange} value={formik.values.lastName} onBlur={formik.handleBlur} autoComplete="off" /> {formik.touched.lastName && formik.errors.lastName && ( <p style={{ color: "red", marginTop: "5px", marginBottom: "-15px" }} > {formik.errors.lastName} </p> )} </Box> <Box> <TextField sx={{ width: "100%" }} id="outlined-email-input" label="Email address" name="email" type={"email"} onChange={formik.handleChange} value={formik.values.email} onBlur={formik.handleBlur} /> {formik.touched.email && formik.errors.email && ( <p style={{ color: "red", marginTop: "5px", marginBottom: "-15px" }} > {formik.errors.email} </p> )} </Box> <Box> <TextField sx={{ width: "100%" }} InputProps={{ startAdornment: ( <InputAdornment position="start">+91</InputAdornment> ) }} id="outlined-mobile-input" label="Mobile Number" type={"tel"} name="mobile" onChange={formik.handleChange} value={formik.values.mobile} onBlur={formik.handleBlur} autoComplete="off" /> {formik.touched.mobile && formik.errors.mobile && ( <p style={{ color: "red", marginTop: "5px", marginBottom: "-15px" }} > {formik.errors.mobile} </p> )} </Box> <Box sx={{ width: "100%" }} > <LocalizationProvider dateAdapter={AdapterDayjs}> <DesktopDatePicker label="Date of birth" inputFormat="DD/MM/YYYY" value={dayjs(formik.values?.dob).format("DD-MM-YYYY") || ""} onChange={(newValue) => { formik.setFieldValue( "dob", dayjs(newValue).format("DD-MM-YYYY") ); formik.setFieldTouched("dob", true); }} renderInput={(params) => ( <TextField sx={{ width: "100%" }} {...params} name="dob" onBlur={formik.handleBlur} error={formik.errors.dob && formik.touched.dob} /> )} /> </LocalizationProvider> {formik.touched.dob && formik.errors.dob && ( <p style={{ color: "red", marginTop: "5px", marginBottom: "-15px" }} > {formik.errors.dob} </p> )} </Box> <Box sx={{ width: "100%" }} > <LocalizationProvider dateAdapter={AdapterDayjs}> <DatePicker views={["year"]} label="Passing year" maxDate={dayjs().subtract(1, "year")} value={formik.values.passingYear || ""} onBlur={formik.handleBlur} onChange={(newValue) => { formik.setFieldValue("passingYear", newValue?.format("YYYY")); }} renderInput={(params) => ( <TextField sx={{ width: "100%" }} {...params} name="passingYear" onBlur={formik.handleBlur} error={ formik.errors.passingYear && formik.touched.passingYear } /> )} /> {formik.touched.passingYear && formik.errors.passingYear && ( <p style={{ color: "red", marginTop: "5px", marginBottom: "-15px" }} > {formik.errors.passingYear} </p> )} </LocalizationProvider> </Box> <Box> <TextField sx={{ width: "100%" }} id="outlined-occupation-input" label="Occupation" name="occupation" type={"text"} onChange={formik.handleChange} value={formik.values.occupation} onBlur={formik.handleBlur} autoComplete="off" /> {formik.touched.occupation && formik.errors.occupation && ( <p style={{ color: "red", marginTop: "5px", marginBottom: "-15px" }} > {formik.errors.occupation} </p> )} </Box> <Box> <Autocomplete className="location" style={{ width: "100%", paddingLeft: "13px", height: "8vh", border: "1px solid rgb(224,224,224)", borderRadius: "6px", fontSize: "17px", fontWeight: "500", color: "#212B36", backgroundColor: "#F9FAFB", "&:focus": { borderWidth: "2px", borderColor: "darken(#2f8f1f, 5%)", fontSize: "20px" } }} apiKey="AIzaSyABX4LTqTLQGg_b3jFOH8Z6_H5CDqn8tbc" onPlaceSelected={(place) => { formik.setFieldValue("location", place?.formatted_address); }} types={["address"]} componentRestrictions={{ country: "us" }} name="location" onChange={formik.handleChange} onBlur={formik.handleBlur} /> {formik.touched.location && formik.errors.location && ( <p style={{ color: "red", marginTop: "5px", marginBottom: "-15px" }} > {formik.errors.location} </p> )} </Box> <Box sx={{ width: "100%" }} > <TextField sx={{ width: "100%" }} id="outlined-password-input" label="Addres" name="address" value={formik.values.address} onChange={formik.handleChange} onBlur={formik.handleBlur} type={"text"} multiline rows={4} maxRows={6} autoComplete="off" /> {formik.touched.address && formik.errors.address && ( <p style={{ color: "red", marginTop: "5px", marginBottom: "-15px" }} > {formik.errors.address} </p> )} </Box> <Box ml={"auto"}> <Button fullWidth size="large" type="submit" variant="contained"> Sign Up </Button> </Box> </Stack> </form> </div> ); }
内容的提问来源于stack exchange,提问作者holoyo
相关产品推荐
相关产品推荐

