I'm getting an infinite loop in the following and can't figure out why.
In one file I have the following declared. Essentially what I'm trying to achieve is to return a stateful errors response which will be updated by revalidating value only when value changes against two schemas (FYI i'm using YUP but that's irrelevant)
export const myValidation = (validationSchema: any, requiredSchema: any, value: any) => {
const [errors,setErrors] = useState([{}]);
useEffect(() => {
Promise.all([
validationSchema.validate(value, { abortEarly: false }),
requiredSchema.validate(value, { abortEarly: false })])
.catch(error => {
let _errors = error.inner.map((err: any) => {
let path = err.path;
let message = err.message;
return { [path]: message };
});
setErrors(_errors);
});
},[value]);
return Object.assign({}, ...errors);
}
I'm referencing this from within my react component as follows:
const errors = myValidation(requiredSchema,validationSchema,{
title: titleValue,
description: descriptionValue
});
titleValue and descriptionValue are both props on the component.
The component itself looks like this:
export default function TitleDescriptionSection({titleValue, descriptionValue, onChange, disabled}: Props) {
const errors = myValidation(requiredSchema,validationSchema,{
title: titleValue,
description: descriptionValue
});
console.log(errors);
return (
<Card><Card.Section>
<FormLayout>
<TextField type="text" label="Title" value={titleValue}
onChange={(value) => onChange({title: value, description: descriptionValue})}
disabled={disabled} error={errors ? errors.title : null}/>
<RichTextField label='Description' value={descriptionValue}
onChange={(value: string) => onChange({title: titleValue, description: value})}
disabled={disabled} error={errors ? errors.description : null}/>
</FormLayout>
</Card.Section>
</Card>
);
}
When the field values change they call onChange which causes the parent to re-render and pass the values for those fields back as props where the are run through myValidation again.
This all works fine until the myValidation catch is triggered and setErrors is called, sending it into an infinite loop. For example there is a validation condition which determines the "title" field to be invalid if it is an empty string.
I believe that the problem is that value (in myValidation) on the re-render is being treated as "changed" on each re-render even though the contents of value hasn't changed from the previous render. I just can't seem to wrap my head around why.