Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to Preserve Array Field Key Stability When Changing Form Data in a Controlled Form? #4397

Open
1 task done
mike-capyh opened this issue Nov 22, 2024 · 0 comments
Open
1 task done
Labels
needs triage Initial label given, to be assigned correct labels and assigned question

Comments

@mike-capyh
Copy link

Prerequisites

What theme are you using?

mui

What is your question?

I'm attempting to add UI/components that modify form state directly.

Making the whole form 'controlled' (in the React sense) by a wrapping component, ie by tying RJSF Form formData and onChange to React.useState, seems to mostly work. The form data can be modified in the wrapper component via the state setter and responds mostly how I'd like. However, I've run into problems with array field key stability. I'll get into details of that below, but it might be an XY problem if there's a better way to take control of form data:

  • Is this kind of 'controlled' RJSF form an intended/supported use case?
    • (The docs seem to imply that the formData prop to Form is only to set default/initial data; perhaps using it this way is a stretch?)
  • Are there any preferred alternatives?
    • (I've considered using an ArrayField custom field and going through its onChange; but this still runs into the key stability issue; going through the array items themselves wouldn't allow eg an append)

The array key stability problem:

Assuming the controlled form setup above, when the form data is updated by calling the state setter (from React.useState), it clobbers the stable keys that the ArrayField sets up internally, ie the ones implemented in #1335 to fix #1046 . As a result they get reset on re-render, and open the door to symptoms that #1335 hoped to prevent.

As a concrete example of what can break: a custom ArrayFieldTemplate with item add/remove animations via react-transition-group might key the transitions off the array item key; when the keys get clobbered, the next array item add animates as if all items (including existing ones) are being newly added.

A work-around?

A (very fragile) work-around is to pass a key remapper function down through eg formContext and having a custom ArrayField field/template call it on re-render, and use the remapped keys as the actual array item keys:

interface FormContext {
  arrayKeyMapper?: (arrayId: string, index: number, key: string) => string
}

That function then has to do a bit of a dance to map "new" internal keys to the old/stable ones, coordinated to any "clobbering" form data change. It might use the indices to do this, but has to be very careful to use those indices 'safely' relative to the actual form data change operation. This... works... but it is a lot of complexity and fragility.

Is there a cleaner way to accomplish this?

Thank you very much for the library, and for your help!

@mike-capyh mike-capyh added needs triage Initial label given, to be assigned correct labels and assigned question labels Nov 22, 2024
@mike-capyh mike-capyh changed the title How to Preserve Array Field Key Stability When Changing Form Data via onChange? How to Preserve Array Field Key Stability When Changing Form Data in a Controlled Form? Nov 23, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
needs triage Initial label given, to be assigned correct labels and assigned question
Projects
None yet
Development

No branches or pull requests

1 participant