Formik+React+TypeScript嵌套对象场景下MUI TextField报未定义错误
Formik+React+TypeScript嵌套表单中MUI TextField的error/helperText报错问题
开发嵌套对象表单时,已正确初始化表单值,但MUI TextField的error和helperText属性始终抛出**"无法读取未定义属性(读取‘emailSubject’)"**的错误。禁用这两个属性后错误消失,可确定问题源于此。尝试过调整validationSchema的嵌套字段验证方案,但问题仍未解决。
组件核心代码
const initialValues: ActionFormValues = { actionType: "send_email", recipient: "", email: { recipients: [], emailSubject: "", emailContent: "" } }; const EmailForm = () => { const { t } = useTranslation(); const [action, setAction] = useState<Action>(initialValues); const [isSubmissionValid, setIsSubmissionValid] = useState(false); const validationSchema = yup.object({ recipient: yup .string() .email(t("FormValidation.Valid_Email")) .test("unique-recipient", t("FormValidation.Email_Exists"), function (value) { const { recipients } = this.parent.email; // Access recipients from the parent object return !recipients.includes(value); }), email: yup.object({ emailSubject: yup.string().required("An email subject is required") }) }); const handleSubmit = (values: ActionFormValues) => { const submission = handleSubmissionCreation(values); console.log(submission); }; const formik = useFormik<ActionFormValues>({ initialValues: action, enableReinitialize: true, validationSchema, onSubmit: handleSubmit }); useEffect(() => { let currentValues = formik.values; if (currentValues.actionType === "send_email") { if (currentValues.email.emailContent !== "" && currentValues.email.emailSubject !== "") { setIsSubmissionValid(true); } } }, [formik.values]); const handleSubmissionCreation = (submittedValues: ActionFormValues): Action => { if (submittedValues.actionType === "send_email") { return { actionType: submittedValues.actionType, email: { recipients: action.email.recipients, emailSubject: submittedValues.email.emailSubject, emailContent: submittedValues.email.emailContent } }; } }; // Handler for adding email const handleAddEmail = (newEmail: string) => { if (newEmail) { // Update the email.recipients array in the state setAction((prevState) => ({ ...prevState, email: { ...prevState.email, recipients: [...prevState.email.recipients, newEmail] } })); // Clear the recipient field and reset its state formik.setFieldValue("recipient", ""); // Clear the value formik.setFieldTouched("recipient", false); // Mark it as not touched formik.setFieldError("recipient", ""); // Clear any errors } }; // Handler for deleting an recipient const handleDelete = (emailToDelete: string) => () => { setAction((prevState) => ({ ...prevState, email: { ...prevState.email, recipients: prevState.email.recipients.filter((recipient) => recipient !== emailToDelete) } })); }; return ( <Box component="form" onSubmit={formik.handleSubmit}> <TextField fullWidth id="recipient" name="recipient" label={t("Common.Recipients")} value={formik.values.recipient} onChange={formik.handleChange} onBlur={formik.handleBlur} error={formik.touched.recipient && Boolean(formik.errors.recipient)} helperText={formik.touched.recipient && formik.errors.recipient} onKeyDown={(ev) => { if (ev.key === "Enter") { if (!formik.isValid) { ev.preventDefault(); return; } handleAddEmail(formik.values.recipient); ev.preventDefault(); } }} inputProps={{ "data-testid": "recipient-field" }} InputProps={{ endAdornment: ( <InputAdornment position="end"> <IconButton aria-label="add recipient" onClick={() => handleAddEmail(formik.values.recipient)} onMouseDown={(e) => e.preventDefault()} disabled={!formik.isValid} > <AddCircle /> </IconButton> </InputAdornment> ) }} /> <Box className="recipient-container"> {action && action.email.recipients.map((data, index) => ( <Chip key={index} label={data} onDelete={handleDelete(data)} /> ))} </Box> <TextField fullWidth id="emailSubject" name="email.emailSubject" label={t("Common.Email_Subject")} value={formik.values.email.emailSubject} onChange={formik.handleChange} onBlur={formik.handleBlur} error={formik.touched.email.emailSubject && Boolean(formik.errors.email.emailSubject)} helperText={formik.touched.email.emailSubject && formik.errors.email.emailSubject} /> <TextField fullWidth id="emailContent" name="email.emailContent" label={t("Common.Email_Message")} value={formik.values.email.emailContent} onChange={formik.handleChange} onBlur={formik.handleBlur} multiline minRows={5} /> <Button variant="contained" type="submit" fullWidth disabled={!isSubmissionValid}> Send Email </Button> </Box> ); }; export default EmailForm;
尝试过的validationSchema调整方案
recipient: yup .string() .email(t("FormValidation.Valid_Email")) .test("unique-recipient", t("FormValidation.Email_Exists"), function (value) { const { recipients } = this.parent.email; // Access recipients from the parent object return !recipients.includes(value); }), email: yup.object().shape({ emailSubject: yup .string() .required("An email subject is required") .transform((value, originalValue) => (originalValue.trim() === "" ? null : value)) .nullable() })
内容的提问来源于stack exchange,提问作者Olivia Bates
相关产品推荐
相关产品推荐

