final-form / react-final-form-arrays

A component for rendering and editing arrays 🏁 React Final Form
MIT License
204 stars 69 forks source link

Changing name prop doesn't change mutator functions #125

Open abrad45 opened 4 years ago

abrad45 commented 4 years ago

Are you submitting a bug report or a feature request?

Bug Report

What is the current behavior?

Changing the name prop does not update the field with the new name's value. All mutators are called on the original data set.

What is the expected behavior?

Changing the name should change the fields modified by the mutator.

Sandbox Link

https://codesandbox.io/s/react-final-form-field-arrays-h3kdl

To reproduce:

  1. Add two customers (customers[x])
  2. Click "Toggle Field Name"
  3. Add two more customers (customers2[x])
  4. Click their delete buttons. They delete customers[x] instead of customers2[x].

This example is contrived, but my use case is not: I have tabs which change the name value passed into the FieldArray prop's render component to allow for localization of similar values. This behavior, for whatever it's worth, diverges from redux-form where similar code worked fine.

What's your environment?

"final-form": "^4.18.7",
"final-form-arrays": "^3.0.2",
"react-final-form": "^6.3.3",
"react-final-form-arrays": "^3.1.1",

Chrome 80, macOS Mojave 10.14.6

Other information

When useFieldArray is first called, useConstant is called and ensures this code really, really never runs again...

https://github.com/final-form/react-final-form-arrays/blob/master/src/useFieldArray.js#L34

It curries the name prop in to all mutators. This means that even if name changes over time, it will still mutate the original set. This seems to be the source of the issue, but I could not begin to know how to resolve without truly changing the way the plugin works and likely breaking something.

Slavvkko commented 4 years ago

I have the same problem. I need to add points to the nested array of currently selected top item. My data:

const lines = [
  {
    color: "#ffffff",
    points: [[0, 0], [1, 1]]
  },
  {
    color: "#ffffff",
    points: [[0, 0], [1, 1]]
  }
]
abrad45 commented 4 years ago

There is a workaround for this issue: add a key prop to each rendered component which matches the field name. This will ensure that React knows that an entirely different component is rendering.

Regardless, I feel this should either be documented or fixed.

killmenot commented 3 years ago

Probably this solution can help with this issue.