'Yup returns always an error even if all fields are valid

Yup is returning always one error in the array even though all fields are valid. The validation is working fine, is checking each field and showing the errors correctly. The form state and the validation is controlled with the below React hook:

import { useCallback, useEffect, useState } from "react";
import { contactSchema } from "./schema";

const useForm = () => {
const [values, setValues] = useState({});
const [touched, setTouched] = useState({});
const [errors, setErrors] = useState([]);

useEffect(() => {
 contactSchema
  .validate(values, { abortEarly: false, context: { value: "GR" } })
  .catch((err) => {
    const schemaErrors = err.inner?.map((err) => {
      return { field: err.path, message: err.message };
    });

    setErrors(schemaErrors);
  });
}, [values]);

const handleChange = (inputName) => (event) => {
 setValues({ ...values, [inputName]: event.target.value });
};

const handleBlur = (inputName) => () => {
 setTouched({ ...touched, [inputName]: true });
};

const canSubmit = () => {
 if (errors.length > 0) {
  errors.forEach((err) => {
    setTouched((prevState) => ({ ...prevState, [err.field]: true }));
  });
}

 return errors.length > 0;
};

const hasError = (field) => {
  let touchedField = null;
  const error = errors.find((fld) => fld.field === field);

  Object.keys(touched || {}).forEach((key) => {
   if (key === field && touched[key]) {
    touchedField = touched[key];
    }
  });

  return touchedField ? error : null;
};

 return {values, handleChange, touched, handleBlur, errors, hasError, canSubmit};
};

export default useForm;

Steps to reproduce:

  1. Fill all fields and see the console.log with the errors array or try to submit the form and check the console.log
  2. The errors array will have one obj even if all fields are valid and the form will not be submitted due to the described issue

Expected behavior: Once all fields are valid the return should be an empty array

I have created this codesandbox with the full code. Thank you in advance for any help!



Solution 1:[1]

The solution is to clear the error state in useEffect every time the effect runs, like below:

useEffect(() => {
 setErrors([]) // this line reset the error state every time the effect runs
 contactSchema
  .validate(values, { abortEarly: false, context: { value: "GR" } })
  .catch((err) => {
    const schemaErrors = err.inner?.map((err) => {
    return { field: err.path, message: err.message };
  });

  setErrors(schemaErrors);
 });
}, [values]);

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 PanosCool