Cyclic dependency, node was:"password" in yup - reactjs

I got the above error. Don't know what happened to the object. My object below.
export const loginValidator = yup.object({
login: yup.string().when('password', {
is: (v) => v < 9999 && v > 999,
then: yup.string().required('Phone No is required').matches(phoneRegExp, 'Must be 10 digits'),
otherwise: yup.string().email().required('Email is required'),
}),
password: yup.string().when('login', {
is: (m) => phoneRegExp.test(m),
then: yup
.string()
.required('Pin is Required')
.matches(/^[0-9]+$/, 'Must be only digits')
.min(5, 'Must be exactly 5 digits')
.max(5, 'Must be exactly 5 digits'),
otherwise: yup.string().required('password is required'),
}),
});
Error I got
Error: Cyclic dependency, node was:"password"
whats going wrong with this
Thanks !!

To avoid Cyclic dependency have to add these values to the yup.
[['login', 'password']]
example,
export const loginValidator = yup.object().shape(
{
login: yup.string().when('password', {
is: (v) => v < 100000,
then: yup.string().required('Phone No is required').matches(phoneRegExp, 'Must be 10 digits'),
otherwise: yup.string().email().required('Email is required'),
}),
password: yup.string().when('login', {
is: (m) => phoneRegExp.test(m),
then: yup
.string()
.required('Pin is Required')
.matches(/^[0-9]+$/, 'Must be only digits')
.min(5, 'Must be exactly 5 digits')
.max(5, 'Must be exactly 5 digits'),
otherwise: yup.string().required('password is required'),
}),
},
[['login', 'password']]
);

Related

React formik mui checkbox inquiry

I am having great difficulty trying to get the error text to appear below my mui checkbox when I yarn dev my signup form. Below is a snippet of the jsx code I used.
``` <FormControlLabel
control={<Checkbox checked={formik.values.termsAndConditions}/>}
label={
<TermsTypography>
I accept the terms and conditions
</TermsTypography>
}
name="termsAndConditions"
onChange={formik.handleChange}
/>```
ValidationSchema:
```const validationSchema = Yup.object({
username: Yup
.string()
.required('Username is required')
.min(8, 'Username should be a minimum of 8 characters in length')
.max(30, 'Username should not exceed 30 characters in length'),
email: Yup
.string()
.email('Enter a valid email')
.required('Email is required'),
password: Yup
.string()
.required('Password is required')
.matches(/^(?=.*[A-Za-z])(?=.*\d)[A-Za-z\d]{8,}$/, 'Password must have at least one letter and number and a minimum of 8 characters')
.min(8, 'Password should be of minimum 8 characters length')
.max(30, 'Password should not exceed 30 characters in length'),
confirmPassword: Yup
.string()
.oneOf([Yup.ref('password'), null], 'Passwords must match'),
termsAndConditions: Yup
.bool()
.oneOf([true], 'You must accept the terms and conditions')
});```
const formik:
```const formik = useFormik({
initialValues: {
username: '',
email: '',
password: '',
confirmPassword: '',
termsAndConditions: false
},
validationSchema: validationSchema,
onSubmit: (values) => {
console.log(values);
setIsLoading(true);
},
});```
I don't think there is an error in my validation Schema or in my formik. From what I have gathered elsewhere on stackoverflow the checkbox is rather tricky. Perhaps the way I am using label for my FormControlLabel is what is causing the issue? I also have my formik and Yup imports imported properly or else my other jsx elements like user name and password would not be showing any error handling. So what am I doing wrong here?

conditionally required field if another field has a value using array of objects

I want to make one field required, but only if the first field has some value on it.
I know I could do something like this, using when if this wasn't an array of objects, but since it is, the validation is not working.
myFieldArray: yup.array().of(
yup.object().shape({
firstField: yup.string(),
secondField: yup.string().when("firstField", {
is: (firstField) => firstField.length > 0,
then: yup.string().required("this field is required"),
}),
})
)
I tried to use yup.ref too, but "when" don't accept refs, only strings
myFieldArray: yup.array().of(
yup.object().shape({
firstField: yup.string(),
secondField: yup.string().when(yup.ref("firstField"), {
is: (firstField) => firstField.length > 0,
then: yup.string().required("this field is required"),
}),
})
)
This one worked
myArray: Yup.array().of(
Yup.object().shape({
firstField: Yup.string(),
secondField: Yup.string().when("firstField", {
is: firstField => firstField && firstField.length > 0,
then: Yup.string().required("this field is required")
})
})
)
Code sandbox => https://codesandbox.io/s/react-formik-yup-forked-wcfkh?file=/src/App.js

Using when validation yup on formik form

Hey guy i have a problem with 2 form input number, min and max, i want the value of max alway greater than min value, if not, using yup to show error, but seem it doesnt work, here is my code. Thank for your help!!
const formikAddFilter = useFormik({
enableReinitialize: true,
initialValues: {
filterName: '',
min: 0,
max: 0,
unValidRange: max > min
},
validationSchema: Yup.object().shape({
unValidRange:Yup.boolean(),
filterName: Yup.string().required('Skill is required'),
max:Yup.number().when('unValidRange',{
is:true,
then: Yup.number().required('max cant less than min')
})
}),
onSubmit: values => {
alert(JSON.stringify(values))
setFilterItem([...filterItem, values])
formikAddFilter.setFieldValue('filterName', '')
formikAddFilter.setFieldValue('min', 0)
formikAddFilter.setFieldValue('max', 0)
}
});
Try this
const validationRange = yup.object().shape({
min: yup.number().required(),
max: yup
.number()
.required()
.test('superior', 'min must be smaller than max', function(f) {
const ref = yup.ref('min');
return f > this.resolve(ref);
})
});
Demo: Stackblitz

how can I check if the password matches with yup

I want to use oneOf but it doesnt work. I want to check If the password and password-Repeat matches. In nodejs it works, but in react native it doesnt work. All errors are shown except password-Repeat. Why?
const registerSchema = yup.object().shape({
fullName: yup.string()
.required('Your name is required.')
.min(4)
.max(40),
email: yup.string()
.required()
.min(6)
.max(255)
.email(),
password: yup.string()
.required()
.min(7)
.max(255),
passwordRepeat: yup.string()
.oneOf([yup.ref('password'), null], 'Password does not match')
});
all my TextInput has values and onChangeText and onBlur and all fields work fine except password repeat
Try this way
Yup.object().shape({
password: Yup.string().required("Required"),
passwordRepeat: Yup.string()
.required("Required")
.when('password', (password, schema) => {
return schema.test({
test: (passwordRepeat) => password === passwordRepeat,
message: 'Password does not match',
});
}),
});

validate if username already exists while typing using Formik and Yup

I have a task from my company where I have to show whether the username is taken or not, I am using formik and yup validation for the checks so for the time being I have added a custom test functionality to yup validation which shows whether the username is taken or not on the click of the submit button, however, my original task was to show the error message dynamically while the user enters the username, it should tell him if the the username is taken or not.
I understood that I might have to manipulate the default handleChange of formik, but I’m unable to do so.
Any help is highly appreciated!!!
validationSchema: Yup.object({
name: Yup.string()
.min(2, "Mininum 2 characters")
.max(30, "Maximum 30 characters")
.required("Your name is required"),
email: Yup.string()
.email("Invalid email format")
.test("email", "This email has already been registered", function (email) {
return checkAvailabilityEmail(email);
})
.required("Your email is required"),
username: Yup.string()
.min(1, "Mininum 1 characters")
.max(15, "Maximum 15 characters")
.test("username", "This username has already been taken", function (username) {
return checkAvailabilityUsername(username);
})
.required("You must enter a username"),
In your validation schema, just add the test function which is found in Yup. Yup also supports async/await as well!
Anyways, to answer your question, here's my example:
validationSchema: Yup.object({
email: Yup.string()
.min(8, 'Must be at least 8 characters')
.max(20, 'Must be less than 20 characters')
.required('Email is required')
.test('Unique Email', 'Email already in use', // <- key, message
function (value) {
return new Promise((resolve, reject) => {
axios.get(`http://localhost:8003/api/u/user/${value}/available`)
.then((res) => {
resolve(true)
})
.catch((error) => {
if (error.response.data.content === "The email has already been taken.") {
resolve(false);
}
})
})
}
),
}),
The value of the email is passed and called to the database which returns a response object. If the response object is an error and the error content is matched, it will be resolved to false and display the message, 'Email already in use'.
EDIT: If you do not want to validate on every keystroke, you can pass in some props, in particular, validateOnChange={false} or ValidateOnBlur={false}. This can help improve performance issues and reduce API calls to your backend!
<Formik
initialValues={{
firstName: '',
lastName: '',
email: '',
}}
validationSchema={validationSchema}
validateOnChange={false} // disable on every keystroke
...
>
To display your error messages accordingly:
{(errors.email && touched.email) && <span style={{ color: 'red', fontSize: '0.8rem', marginLeft: '1.5rem' }}>{errors.email}</span>}

Resources