fix(form): prevent reload loop with rjsf v5.20 #75
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Closes #72
rjsf 5.20 was causing issues with our e2e tests since sometimes, when dragging new (e.g. select) fields to the tree some of them would be typed as text fields. This is related to our use of
rawErrors
in the our custom validation function to pass down the path toFieldTemplate
.It turns out the error was being caused by this change in rjsf. That
mergeObjects
there with thepreventDuplicates
argument returns a deep copy of the object when called with two equal objects, meaning that theerrorSchema
object returned is essentially a new one.properties.content.props
inObjectFieldTemplate
containserrorSchema
, therefore it reloads when theerrorSchema
changes (after that change in rjsf it now does so on every validation call), causingcards
to change, causing theuiSchema
to be updated in the store, causing theForm
inSchemaTree
to refresh (asuiSchema
is an object anduseSelector
uses a shallow equality check*), triggering a new validation, and continuing the endless loop.The solution has been to add an extra check in
ObjectFieldTemplate
so that changes incards
only dispatch an update to theuiSchema
when the order of the cards changes, and not in every situation when the cards array changes (which in fact happens on every re-render as it's an array and arrays are compared by reference, returning false even if both arrays have the same content, which is generally the case here). This breaks that loop.Note: The way we use
rawErrors
to pass the path to theFieldTemplate
is a bit hackish, but seeing that it keeps working after this change I would maintain it for the time being. There is no rjsf way of getting the path information functions such astoPathSchema
only return the "path" from the current element to its children, but not from the root to the current element, which is what we need. So, the alternative, if we end up wanting to change this, could be to have apaths
object in the redux store and populate it in theaddByPath
action, and we also would have to populate it on startup when loading an existing schema by traversing it completely. We would also have to disallow duplicate field ids everywhere in the form.*We should consider using Immer for the Redux state to better protect ourselves against these situations