final-form / react-final-form

🏁 High performance subscription-based form state management for React
https://final-form.org/react
MIT License
7.38k stars 480 forks source link

Field name and value not in sync when changing field name #869

Open capJavert opened 3 years ago

capJavert commented 3 years ago

What is the current behavior?

React final form does not swtiche values when field name is dynamically changed during component life, for example if we have:

const { input: { value } } = useField(name)

Imagine name is coming from props and can be dynamically changed.

Initial form state: { a: 1, b: 2 }

Renders:

  1. props { name: 'a' }, input: { value: 1 }
  2. props { name: 'b' } input: { value: 1 } - changed the field name, value is still stale
  3. props { name: 'b' } input: { value: 2 } - in next rerender name and value are in sync

So the case can exist where the source changed but the value is still from previous source.

This can break any component that expects specific value for specific source. And can also introduce wrong values (for example during auto save).

What is the expected behavior?

Renders:

  1. props { name: 'a' }, input: { value: 1 }
  2. props { name: 'b' } input: { value: 2 } - name and value are in sync in first render after name change
  3. props { name: 'b' } input: { value: 2 } - ...

Sandbox Link

https://codesandbox.io/s/final-form-field-name-and-value-not-in-sync-when-changing-field-name-okbtn

Click the button to change field name from a to b and watch console for output.

What's your environment?

"react": "16.13.1",
"react-final-form": "6.4.0",
"final-form": "4.19.1"

Any OS/Browser.

capJavert commented 3 years ago

I just got the chance to test it out on latest releases:

"react": "16.13.1",
"react-final-form": "6.5.2",
"final-form": "4.20.0"

Bug is still present. I also updated codesandbox.

capJavert commented 3 years ago

@erikras any comment or advice on how to debug/fix this further? I would be open to fixing with some pointers from you or some of the contributors.

ruscoder commented 3 years ago

I also encountered this issue. Workaround for now - specify key={fieldName} attribute in the parent component.

capJavert commented 3 years ago

I am not sure that would help because we tried that before and still there was a stale value during rerenders. Could you do a repro on my example? @ruscoder

gbiryukov commented 2 years ago

also facing this issue on most recent versions.

it happens because useField returns same name as it receives from props while related value comes from state that is updated in effect after name change.

possible solution is to have second version of name also in state and update it synchronously with value. this way hook can return values in sync