Повторяющиеся ошибки при проверке Formik / Yup - PullRequest
0 голосов
/ 22 апреля 2020

Я использую следующую схему проверки в 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 , когда пользователь вводит несколько недействительных адресов электронной почты, они получить сообщение об ошибке один раз для недействительного адреса электронной почты.

Как-нибудь обойтись?

Вот ссылка на песочницу: https://codesandbox.io/s/wild-sea-h2i0m?file= / src / App.tsx

1 Ответ

2 голосов
/ 26 апреля 2020

Что вы хотите сделать, это убедиться, что вы отфильтровываете дублирующиеся ошибки. Вы должны убедиться, что каждое сообщение об ошибке уникально. Я написал функцию, которая поможет вам сделать это.

Я обновил ваш 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;

...