Formik/Yup 验证中的重复错误
Duplicate Errors on Formik/Yup Validation
我在 Formik 中使用以下验证模式:
validationSchema = {
Yup.object({
emails: Yup.array()
.of(Yup.string().email('Please enter valid email addresses only.'))
.min(1, 'At least one email address is required.')
})
}
它工作得很好,除了因为我使用的是 Material UI AutoComplete 组件,当用户输入多个无效的电子邮件地址时,他们会看到每个无效的电子邮件地址一次错误消息。
有什么解决办法吗?
这是一个沙盒 link:https://codesandbox.io/s/wild-sea-h2i0m?file=/src/App.tsx
然后您要做的是确保过滤掉重复的错误。您应该确保每条错误消息都是唯一的。我写了一个函数来帮助你做到这一点。
我更新了你的 EmailsField
组件:
import React from "react";
import Autocomplete from "@material-ui/lab/Autocomplete";
import Chip from "@material-ui/core/Chip";
import CloseIcon from "@material-ui/icons/Close";
import TextField from "@material-ui/core/TextField";
import { FieldProps } from "formik";
const isEmailValid = (email: string) =>
/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
const EmailsField = ({
field,
form: { errors, touched, setTouched, setFieldValue },
...props
}: FieldProps) => {
console.log('errors', errors)
const name = field.name;
const [value, setValue] = React.useState<string[]>([]);
const [inputValue, setInputValue] = React.useState("");
const handleChange = (event: React.ChangeEvent<{}>, emails: string[]) => {
setTouched({ ...touched, [name]: true });
setValue(emails);
event.persist();
setFieldValue(name, emails);
};
const handleInputChange = (
event: React.ChangeEvent<{}>,
newInputValue: string
) => {
const options = newInputValue.split(/[ ,]+/);
const fieldValue = value
.concat(options)
.map(x => x.trim())
.filter(x => x);
if (options.length > 1) {
handleChange(event, fieldValue);
} else {
setInputValue(newInputValue);
}
};
// 1. This function will help remove duplicated errors
const getEmailErrors = (errors: any) => {
return Array.isArray(errors)
? errors.filter((email: string, i: number, arr: any) => arr.indexOf(email) === i)
: errors;
}
return (
<Autocomplete<string>
multiple
disableClearable={true}
options={[]}
freeSolo
renderTags={(emails, getTagProps) =>
emails.map((email, index) => (
<Chip
deleteIcon={<CloseIcon />}
variant="default"
label={email}
color={isEmailValid(email) ? "primary" : "secondary"}
{...getTagProps({ index })}
/>
))
}
value={value}
inputValue={inputValue}
onChange={handleChange}
onInputChange={handleInputChange}
renderInput={params => (
<TextField
{...params}
name={name}
error={touched[name] && Boolean(errors.emails)}
//---------------------------------------->>>> Call it here
helperText={touched[name] && errors.emails && getEmailErrors(errors.emails as any)}
variant="outlined"
InputProps={{ ...params.InputProps }}
{...props}
/>
)}
/>
);
};
export default EmailsField;
我在 Formik 中使用以下验证模式:
validationSchema = {
Yup.object({
emails: Yup.array()
.of(Yup.string().email('Please enter valid email addresses only.'))
.min(1, 'At least one email address is required.')
})
}
它工作得很好,除了因为我使用的是 Material UI AutoComplete 组件,当用户输入多个无效的电子邮件地址时,他们会看到每个无效的电子邮件地址一次错误消息。
有什么解决办法吗?
这是一个沙盒 link:https://codesandbox.io/s/wild-sea-h2i0m?file=/src/App.tsx
然后您要做的是确保过滤掉重复的错误。您应该确保每条错误消息都是唯一的。我写了一个函数来帮助你做到这一点。
我更新了你的 EmailsField
组件:
import React from "react";
import Autocomplete from "@material-ui/lab/Autocomplete";
import Chip from "@material-ui/core/Chip";
import CloseIcon from "@material-ui/icons/Close";
import TextField from "@material-ui/core/TextField";
import { FieldProps } from "formik";
const isEmailValid = (email: string) =>
/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
const EmailsField = ({
field,
form: { errors, touched, setTouched, setFieldValue },
...props
}: FieldProps) => {
console.log('errors', errors)
const name = field.name;
const [value, setValue] = React.useState<string[]>([]);
const [inputValue, setInputValue] = React.useState("");
const handleChange = (event: React.ChangeEvent<{}>, emails: string[]) => {
setTouched({ ...touched, [name]: true });
setValue(emails);
event.persist();
setFieldValue(name, emails);
};
const handleInputChange = (
event: React.ChangeEvent<{}>,
newInputValue: string
) => {
const options = newInputValue.split(/[ ,]+/);
const fieldValue = value
.concat(options)
.map(x => x.trim())
.filter(x => x);
if (options.length > 1) {
handleChange(event, fieldValue);
} else {
setInputValue(newInputValue);
}
};
// 1. This function will help remove duplicated errors
const getEmailErrors = (errors: any) => {
return Array.isArray(errors)
? errors.filter((email: string, i: number, arr: any) => arr.indexOf(email) === i)
: errors;
}
return (
<Autocomplete<string>
multiple
disableClearable={true}
options={[]}
freeSolo
renderTags={(emails, getTagProps) =>
emails.map((email, index) => (
<Chip
deleteIcon={<CloseIcon />}
variant="default"
label={email}
color={isEmailValid(email) ? "primary" : "secondary"}
{...getTagProps({ index })}
/>
))
}
value={value}
inputValue={inputValue}
onChange={handleChange}
onInputChange={handleInputChange}
renderInput={params => (
<TextField
{...params}
name={name}
error={touched[name] && Boolean(errors.emails)}
//---------------------------------------->>>> Call it here
helperText={touched[name] && errors.emails && getEmailErrors(errors.emails as any)}
variant="outlined"
InputProps={{ ...params.InputProps }}
{...props}
/>
)}
/>
);
};
export default EmailsField;