Data loss when using controlled style?

I am having some issues with data loss using the React component and made an issue with a reproduction (Data loss when using React controlled style · Issue #2174 · eclipsesource/jsonforms · GitHub), but I didn’t want to clutter up that issue with and extended discussion.

I’m wondering whether I’m actually the first one to have this problem. Did anyone else experience something similar when integrating forms into a greater whole, and how did you deal with it? Maybe a workaround exists already?

Hi @jwueller,

You’re right that the JsonForms component design is not ideal here. The underlying problem is that we behave like a “controlled” component, however we maintain our own data state internally and therefore have to sync it with the incoming one whenever that changes.

That design smell is also why there is a small debounce in the JSON Forms component: The forms auto-fill mechanism of Chrome entered data so fast that JSON Forms was stuck in an endless rerender loop.

Note that there is also an additional (much larger) debounce in the Material UI renderers, to reduce rerenderings while users are typing.

All of this is not a problem in the most common use case: Some initial form data is handed over, the only source of manipulation is the user and the edited data is then further processed somewhere else.

In use cases where we need to double sync between form and some other data source we’re usually solving this by waiting for the user to stop editing. Only then do we update the form data with the new/additional data from the other source. This is easily done if you use a renderer set which indicates whether a user is currently editing the form. With the current off-the-shelf renderer sets that’s not possible out of the box.

A clean solution would be to properly separate the controlled and uncontrolled use cases and not handle them both with the same code paths.

For example in the uncontrolled use case we would only take in initialData but then ignore any prop changes to it. In the controlled use case we should then not update our internal state but let the user hand us back (potentially modified) data and errors.

If you like to help us achieve this cleaner architecture then this would be awesome of course. However before you create such a (potentially larger) PR we should probably align on the architectural details.

Thanks for the insight!

This indeed sounds like it needs a major rework. I’m not sure if I will have the time to do this one at the moment, but I might be able to contribute if there is some kind of initiative with a clear goal.

I do feel like it shouldn’t be a performance concern to just update some input values, even if it happens 60 times per second. Maybe this just needs some clever memoization to prevent excessive recomputation of the layout and unnecessary re-renders of unmodified components.

Would it be possible to get rid of that internal state entirely and only wrap the core form with it’s own state when needed? Going from controlled to uncontrolled seems a lot more feasible than the other way around.

We already invested some effort in memoization. However the validation runs on every data change and the bindings run on every render before memoization takes place. This can’t be changed without some reworkings in the JSON Forms React bindings and probably some adaptions in JSON Forms core to suit the new approach in the bindings.

Yes that’s possible. JSON Forms core is basically just a collection of utils. So you would an alternative “JsonForms” React component which behaves like you expect. The bindings is not too much code, so I think a small POC could be developed quite quickly to validate the approach.