Performance issue - lag happening on typing

Hi, I’m using JSON forms standalone with React and I have integrated custom renderer with Quill for some of the inputs to be editors. The forms are part of a view in mobile application developed with React + Cordova. The problem I have is that when the form has more than 8-10 inputs the typings appear really slow on the input field kind of a lag happening between the typing on keyboard and the letters showing on the input. This happens only on Android though. From what I have inspected the main cause of the delay is the handleChange on the . I have tried different workarounds, one was with using the onBlur function on Quill to invoke the handleChange for JsonForms instead on onChange which improved the performance a lot but unfortunately had problems with saving the last typed input and wasn’t the option. Do you have any suggestion on how to improve the performance on typing for this kind of scenario and is there going to be any improvements for the onChange function in later versions?

Great feature by the way, really nifty in my situation.

[original thread by Jovana Markovska]

Hi @jovana-markovska thanks for your interest in JSON Forms! There are two places where we need to look:

  1. Whenever data changes JSON Forms will execute the validation on the whole form. For text inputs with fast typers this might lead to slowdowns, depending on how large the form is. This is something we want to fix in the long run by debouncing the input (probably within handleChange): Only apply the input, validate and emit an update change once the user stops typing for a short while. It seems you did something similar on your end to improve the performance. When using timeouts in combinations with onChange instead of onBlur you might be able to implement this yourself.

  2. Make sure that JsonForms isn’t fed its emitted data object again. This would trigger an expensive re-rendering including validation on each each data change (additionally to the one triggered by handleChange). We usually handle this by storing the updated form data within a useRef.

Hi both.

I’m pretty sure i’m experiencing a similar issue. I have a data object that when all whitespace is removed is 21,242 characters. My schema is made up of multiple levels of nested objects but in total there are roughly 50 properties that result in user editable fields within my display (Controls?). Any time I add a new character to any text field it takes roughly 3 seconds to update.

With regards to your suggestions @sdirix

  1. how should I go about adding this? Should I add a custom renderer that essentially replaces the standard control for displaying text fields and update the onChange function to add the wait a second or two before validating the form?
  2. Is this something that I can do or is this something that you’re looking at? If it’s something for me to look at what are some tell tale signs that I might be doing this?

I manage to massively reduce lag when typing into the text field by following your suggestion of creating a custom text control and debouncing the handleChange in the onChange.

The custom text control was copied from the existing text control and I replaced the onChange with the following:

    const debouncedChange = useCallback(
        debounce((nextInputText: any)=>{handleChange(path, nextInputText)}, 1000),
        []
    )
    const onChange = (ev: any) => {
        setInputText(ev.target.value);
        debouncedChange(ev.target.value);
    }

Sounds good! 3 seconds for a single render pass is a lot though. What does your form look like? Do you have arrays?

Yes I have lots of nested arrays of objects. I think the deepest level of nesting I have is about 4 objects deep. I.e. a top level object has an array of objects, each second level object has an array of objects each third level object has an array of objects.

I see. We have reported performance issues regarding arrays / tables that too much is rerendered when the form updates. We’ll definitely take a look at them in the nearish future, so at some point this might improve for you.

Are you using only the array-layout renderer or also the table renderer?

1 Like

My top level object I use the ListWithDetail and then for every other object I just let JSON forms do it’s thing, so whatever the default is?