I use [email protected] in my application. There is some fields where i need to define a validate function dynamically. Note that I need id and slice to look for the correct field in values
<Field
component={SemanticFormField}
as={Input}
placeholder="From"
name={"participation-card-" + id + "-slice-" + slice + "-min"}
validate={[number]}
/>
<Field
component={SemanticFormField}
as={Input}
placeholder="to"
name={"participation-card-" + id + "-slice-" + slice + "-max"}
validate={[number, validateMaxSlice(slice, id)]}
/>
When i define validateMaxSlice like this
const validateMaxSlice = (slice, id) => (value, values) => {
const min = values["participation-card-" + id + "-slice-" + slice + "-min"];
return min >= value ? "Invalid slice" : undefined;
};
Or inline like this
validate={[number, (value, values) => {
const min = values["participation-card-" + id + "-slice-" + slice + "-min"];
return min >= value ? "Invalid slice" : undefined;}]
The application goes in an infinite loop the moment it renders the component.
The question is why and how to fix it ?
Edit:
Thank you for your help ! Here is how I implement it
Container part:
createSlice() {
const id = uuidv4();
return {
id,
validators: (value, values) => {
const min = values["participation-card-" + this.props.id + "-slice-" + id + "-min"];
return valSup(value, "Tranche incorrecte")(min);
},
};
}
addParticipationSlice() {
let participationSlices = this.state.participationSlices;
participationSlices.push(this.createSlice());
this.setState({
participationSlices,
});
}
Scene part:
<Field
component={SemanticFormField}
as={Input}
name={"participation-card-" + id + "-slice-" + slice.id + "-max"}
size="mini"
width={7}
validate={[number, slice.validators]}
/>
As you are creating validators on the fly, it create a new validator instance every time it redraw.
On the first redraw, React try to validate the value, then redraw to update the view. This, in turn, create a new validate function and change the related props value.
As you change the props to the component, react will trigger a re-render of the Field. Thus causing it to revalidate again, causing again a re-render.
One way to correct it is to generate one and only one version of each callback, reusing functions instances when appropriate.
You can for example store a this.validators associative array then change your function generator to something like this:
validateMaxSlice(slice, id) => {
if (!this.validators[`${slice}-${id}`]) {
this.validators[`${slice}-${id}`] = (value, values) => { ...Actual validation code... }
}
return this.validators[`${slice}-${id}`]
}
This way, validators are created on the fly but reused where they need to be.