Rerendering issues after upgrading to React 18

We use JsonForms in several places throughout our application. In some of those places where we have more complicated forms, using several custom renderers and updating a context with the updated data we have run into performance issues after upgrading from React 16 to 18.

We are using vanilla renderers as a base plus our own custom renderers. We also have renderers that wrap the base renderers using dispatch components.

When entering data (both on a standard textbox and in custom renderers) we have issues where typing fast or clicking a spinner quickly results in the data skipping characters and sometimes looping between two values once we stop typing/clicking. This did not occur in the same components prior to the react upgrade.

We have upgrade to the latest JsonForms version, which did not resolve the issue. We haven’t tried to revert React back to version 16, although we did try using the v16 render instead of createRoot in case the new concurrency model was part of the issue - that also resulted in no change to the behavior.

We are currently trying to find workaround to improve the experience in various components at issue, but were hoping this community could provide some insight on how to address the issues more globally (React settings, JsonForms config, etc.)

Hi @Turntwo,

Can you verify that the behavior also occurs without custom renderers? If yes, can you give us the example to reproduce, e.g. example schema, uischema and data?

If it only occurs with custom renderers, can you post their code and ideally an integrated example which we can build and inspect ourselves?

We tested this morning removing all but a single text field from the schema, so I can verify that the issue still occurs without any custom renderers. Unfortunately I can’t provide a sample of the actual code, and a simplified example app wouldn’t reproduce the problem (only happens in some areas of our application).

We have the json data object stored in a context that gets updated through the handleChange events on the jsonforms components, and are looking in to that causing a race condition with the re-renders that didn’t occur with the previous version of React.

We wanted to see if anyone else had experienced a similar issue when upgrading from React 16 to 18, and had a fix based on some React or JsonForms settings.

We are continuing to research on our end and I will post any updates as we gather more information and narrow down the root cause of the issue.

Removing an atlaskit ModalTransition from a different modal on the page has improved the issue - we can still make it happen but it is less obvious - have to type or click pretty fast to get it to cycle.

Some points which might be relevant or not:

Regarding performance, please make sure that all props handed over to JSON Forms are stable, for example by memoizing them. If for example a new renderers array is handed over to JSON Forms with each render call, then the whole form will rerender all the time.

In case you don’t have any prop changes during the lifetime of the form, then you don’t need to hand over the emitted data back to JSON Forms.

With the new middleware support you can build a “controlled” variant of JSON Forms, to specifically control the internal state of JSON Forms from the outside. See here for an example. Use this in case you constantly process data changes from outside the forms (e.g. from a backend) which need to be merged with the forms’ state.

Thanks, those are helpful tips. If we don’t use them here I think we have some other use cases where that could be important.

We’ve mostly resolved the upgrades issues by refactoring the problematic components. In one instance moving context lower in the hierarchy to avoid re-rendering a large grid component (would have been a good spot for your second suggestion, so the context updates didn’t re-render the forms).

In a different case, reworking how we handled dependent state updates in the data object and reworking a custom date renderer have mostly resolved the issues (might be a good use case for middleware, currently we have a “renderer” that wraps the form to apply custom logic) - although we still had to work around some issues where the onchange updates to context state were overwritting each other with old data, and setting a default date in the date renderer wasn’t being reflected in the context data after calling handleChange in the renderer. We found workarounds, so should be OK.

Appreciate the help, especially since we couldn’t provide source code examples.