英文:
Dynamically change Yup message in Array custom validation. Return Array error messages
问题
Problem: But when .test()
function returns an array - I have an error string (not array string).
Solution: We can get the array like this:
arrayValidation.validate(["test UNIQUE", "fail", "fail"])
.then(result => console.log("success: ", result))
.catch(error => console.log("error: ", error.errors)) // => our array
BUT how to get the array in Formik? For some reason, I get only a string and not an array.
Here is an example:
import { useFormik } from "formik";
import * as Yup from "yup";
import { useEffect } from "react";
export const arrayValidation =
Yup.array()
.min(1)
.max(5)
.of(Yup.string().required("Required"))
.test(
'unique',
(value) => {
const message = "The value must be unique, but you have a copy in the field "
const uniqueFieldIds: (string | null)[] = [];
for (let i = 0; i < value.originalValue.length; i++) {
const targetStr = value.originalValue[i];
for (let j = 0; j < value.originalValue.length; j++) {
const str = value.originalValue[j];
if (j !== i && targetStr === str) {
uniqueFieldIds.push(message + (j + 1));
break;
}
}
if (!uniqueFieldIds[i]) {
uniqueFieldIds[i] = null;
}
}
console.log("uniqueFieldIds: ", uniqueFieldIds);
return uniqueFieldIds;
},
(value) => {
return value ? value.length === new Set(value)?.size : true;
}
)
arrayValidation.validate(["test UNIQUE", "fail", "fail"])
.then(result => console.log("success: ", result))
.catch(error => console.log("error: ", error.errors))
const TestComponent = () => {
const formik = useFormik({
initialValues: {
arrayStrings: ["test UNIQUE", "fail", "fail"],
},
validationSchema: Yup.object({
arrayStrings: arrayValidation,
}),
onSubmit: (values, { setSubmitting }) => {
// ...
setSubmitting(false);
}
});
useEffect(() => {
formik.submitForm();
}, [])
useEffect(() => {
console.log("errors: ", formik.errors.arrayStrings); // "errors occurred" (string)
console.log("TYPEOF errors: ", typeof formik.errors.arrayStrings); // string (not object)
console.log("errors: ", (formik.errors.arrayStrings as any).errors); // undefined
}, [formik.errors])
return (
<div>
</div>
)
}
export default TestComponent;
What am I doing wrong? Thanks for your answers.
英文:
Task:<br>I need to check every element in the array - unique item.
And I want to show the user, where exactly he has failure string(like a, in the second and third fields you have an identical values).<br>
My solution<br>
So, I found a solution using Yup.Array().test(...)
, and more concrete there it is:
export const arrayValidation =
Yup.array()
.min(1)
.max(5)
.of(Yup.string().required("Required"))
.test(
'unique',
(value) => {
const message = "The value must be an unique, but you have the copy in the field "
const uniqueFieldIds: (string | null)[] = [];
for (let i = 0; i < value.originalValue.length; i++) {
const targetStr = value.originalValue[i];
for (let j = 0; j < value.originalValue.length; j++) {
const str = value.originalValue[j];
if(j !== i && targetStr === str) {
uniqueFieldIds.push(message + (j + 1));
break;
}
}
if (!uniqueFieldIds[i]) {
uniqueFieldIds[i] = null;
}
}
console.log("uniqueFieldIds: ", uniqueFieldIds);
return uniqueFieldIds;
},
(value) => {
return value ? value.length === new Set(value)?.size : true;
}
)
arrayValidation.validate(["test UNIQUE", "fail", "fail"])
.then(result => console.log("success: ", result))
.catch(error => console.log("error: ", error)) // => Why is it not the array?
Problem<br>
But when .test()
function returns an array - I have an error string(not array string).<br>
If array has 2 identical lines, then error is "2 error occured", but test()
return value is array, soft of
["The value must be an unique, but you have the copy in the field 2", "The value must be an unique, but you have the copy in the field 1"]
EDIT:
We can get the array just like that:
arrayValidation.validate(["test UNIQUE", "fail", "fail"])
.then(result => console.log("success: ", result))
.catch(error => console.log("error: ", error.errors)) // => our array
BUT how to get the array in the formik? For some reason I get only string, and not array.
Here is an example:
import {useFormik} from "formik";
import * as Yup from "yup";
import {useEffect} from "react";
export const arrayValidation =
Yup.array()
.min(1)
.max(5)
.of(Yup.string().required("Required"))
.test(
'unique',
(value) => {
const message = "The value must be an unique, but you have the copy in the field "
const uniqueFieldIds: (string | null)[] = [];
for (let i = 0; i < value.originalValue.length; i++) {
const targetStr = value.originalValue[i];
for (let j = 0; j < value.originalValue.length; j++) {
const str = value.originalValue[j];
if(j !== i && targetStr === str) {
uniqueFieldIds.push(message + (j + 1));
break;
}
}
if (!uniqueFieldIds[i]) {
uniqueFieldIds[i] = null;
}
}
console.log("uniqueFieldIds: ", uniqueFieldIds);
return uniqueFieldIds;
},
(value) => {
return value ? value.length === new Set(value)?.size : true;
}
)
arrayValidation.validate(["test UNIQUE", "fail", "fail"])
.then(result => console.log("success: ", result))
.catch(error => console.log("error: ", error.errors))
const TestComponent = () => {
const formik = useFormik({
initialValues: {
arrayStrings: ["test UNIQUE", "fail", "fail"],
},
validationSchema: Yup.object({
arrayStrings: arrayValidation,
}),
onSubmit: (values, {setSubmitting}) => {
// ...
setSubmitting(false);
}
});
useEffect(() => {
formik.submitForm();
}, [])
useEffect(() => {
console.log("errors: ", formik.errors.arrayStrings); // "errors occurred" (string)
console.log("TYPEOF errors: ", typeof formik.errors.arrayStrings); // string, (not object)
console.log("errors: ", (formik.errors.arrayStrings as any).errors); // undefined
}, [formik.errors])
return (
<div>
</div>
)
}
export default TestComponent;
What am I doing wrong?<br>
Thanks for your answers
答案1
得分: 0
根据我理解,使用React似乎没有一种正常的方法。是的,你可以在纯JavaScript中执行这个操作:
arrayValidation.validate(["test UNIQUE", "fail", "fail"])
.then(result => console.log("success: ", result))
.catch(error => console.log("error: ", error.errors)) // error.errors对象
但在React+Formik中,你只能:
1)使用strArray.toString()
连接结果字符串,或者使用strArray.join()
作为示例。
2)然后你需要在Formik中解析这个字符串。
3)然后使用解析后的值。
感谢@usama 的评论,这些评论有助于创建这个答案。
英文:
As far as I understand there are no a normal way using React. Yes, you'll be able to do this in vanilla js:
arrayValidation.validate(["test UNIQUE", "fail", "fail"])
.then(result => console.log("success: ", result))
.catch(error => console.log("error: ", error.errors)) // error.errors object
But in the React+Formik you can only:
- concatenate resulting string using strArray.toString() or example using strArray.join().
- Then you ought to parse this string in the formik.
- And then use the value from the parsed string
Thanks to @usama for the comments that helped to create this answer
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论