I have kind of a convoluted use case here. I have an API that responds with a JSON that maps to React components, including form fields (their values, validations, etc). Every component in the page receives props from the backend, so if I make a request I have to update those props, that's why I save the props to state
and call setState
after every request that should re-render the components.
So I have a RFF with two fields. The form initial value comes from the backend as well as the fields' initial validations (the json maps to validation functions).
I am using this Auto Save with debounce example to send a request to the backend every time the user completes the form and it's valid. Now comes the tricky part for me.
The form must receive the new values from the backend (I do this by calling a function that builds the form values from the page state
inside <Form initialValues={fn} />
, that causes the form to re-render with the new values in sync with the state) but it also receives the new validations (they can change depending on the values, for example, if field 2 should be at least 20% of field 1), but the form only shows validations on blur or when an input changes.
Also, the fields are text+dropdowns, and when I select an option another request is sent with the new dropdown value (this is desired behavior) but then the response comes in and it updates the fields' values and then ANOTHER request is sent because the inputs changed (this is NOT a desired behavior, and it has to do with the Auto Save
example, the diff part).
So, to try and explain it better:
field1: {
value: '500',
dropdown_value: 'A',
validation_value: '100',
validation_msg: 'value must be 100 or more', // this depends on validation_value
},
field2: {
value: '1000',
dropdown_value: 'B',
validation_value: '300',
validation_msg: 'value must be 300 or more', // this depends on validation_value
},
// other components props...
600
in the first field<AutoRequest />
fires a debounced request with response:field1: {
value: '600',
dropdown_value: 'A',
validation_value: '100',
validation_msg: 'value must be 100 or more',
},
field2: {
value: '1000',
dropdown_value: 'B',
validation_value: '9999', // changed
validation_msg: 'value must be 9999 or more', // changed, now the field is invalid
},
// other components props...
<AutoRequest />
fires a new debounced request with response:field1: {
value: '7777', // changed, value transformed in the backend
dropdown_value: 'A2', // changed
validation_value: '7777', // changed
validation_msg: 'value must be 7777 or more', // changed but valid
},
field2: {
value: '8888', // changed
dropdown_value: 'B2', // changed
validation_value: '8888', // changed
validation_msg: 'value must be 8888 or more', // changed but valid
},
// other components props...
I know it's a long post, I'm sorry, but this has been troubling me for a while and I've solved issues in isolation, but when all of these requirements come together I can't seem to find a solution that fits every need of my use case.
I ended up with a solution that I don't like too much but it gets the job done for my use case: https://codesandbox.io/s/ejemplo-react-final-form-nrpgbp
It simulates an auto request that changes the inputs, but it's also fired every time a form value is changed, so in this case is only for testing the change in a dropdown (if you change the inputs, it will infinitely send new requests. If you want to test that, you will have to modify the request response to match your inputs' current values). Also, the validations change on request and they are fired up as the form re-renders instead of on change or blur.