Shopify / quilt

A loosely related set of packages for JavaScript/TypeScript projects at Shopify

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

`@shopify/react-form`: `dynamicList` gets reset when running `makeClean()` (or `dynamicList.newDefaultValue()`)

jakobbouchard opened this issue · comments

Overview

I am using a dynamicList to create different tiers for a discount app. When loading a discount, I try to set the configuration using configuration.newDefaultValue(...), and while it (very quickly) adds the config to the data, it also immediately resets it to the previous default value. This behaviour can also be observed if I instead add the tiers manually in a way similar to this:

discountConfiguration.forEach(tier => configuration.addItem(tier));
makeClean(); // From useForm(...)

The items get correctly added if I don't run makeClean(), but then the form is dirty, which is not what I want.

The makeCleanOnSubmit option from useForm(...) also triggers this bug.

Consuming repo

Private repo

It seems that reinitializeAction(...) gets called twice. Once when running newDefaultValue(...) and then once again with useEffect(...). The first time it gets called with the right arguments, the new value, but the second time it resets it to the initial list. I assume is supposed to be the desired behaviour, but I think dispatch changes when setting a new default value somehow and as such, the effect runs, and with the new data not matching the old one, it gets reset. It seems that dispatch stable, according to the React docs. Maybe it could be removed from the dependencies then?

Also, I am unsure of the need for this effect at all. In theory, shouldn't list stay the same anyways?

Last thing to note: removing all dependencies from the array does fix the problem since it only runs once.

Hey! Just bumping this, since I reported it over a month ago and I still don't have any update. This is still not fixed and using newDefaultValue(...) on a dynamic list doesn't work.

Having the same issue as above. Did you find any work arounds @jakobbouchard ?

The project I'm working on has been on hold for other reasons, so I haven't gone back to try and fix it yet, but I didn't find any workarounds during that time.

I've experienced the same problem. Seems like it is still not solved.
Thanks, @jakobbouchard for the workaround by all dependencies from the array. I've ended up implementing an empty useMemo array so that nothing gets triggered.

commented

@moyamejiasr I experience the same problem. Could you please share how to fix it by code?

Also experiencing this with nested fields:

const formFields = {
  notNestedField: useField(""),
  field: {
    subField: {
      subSubField1: useField(""),
      subSubField2: useField("")
    }
  }
}

  const {
    fields,
    submit,
    submitting,
    dirty,
    reset,
    submitErrors,
    makeClean,
  } = useForm({
    fields,
    async onSubmit(form) {}
  }

makeClean and newDefaultValue works on the notNestedField but clears the value of all the nested fields.

EDIT:
After investigating further it seems to be related to arrays and not with nested fields. When a field is an array and I run makeClean or newDefaultValue, all fields with an array for the value gets reset.

Alright so I've found a work around but it's really not ideal. The work around is simply to stringify the arrays. So it would look something like that:

const formFields = {
  arrayField: useField("[]"),
}

  const {
    fields,
    submit,
    submitting,
    dirty,
    reset,
    submitErrors,
    makeClean,
  } = useForm({
    fields,
    async onSubmit(form) {}
  }

// When reading the value
const fieldValue = JSON.parse(fields.arrayField.value);
fieldValue.map(...)

// When updating the value
const updatedArray = [
  ...fieldValue,
  newValue
]
fields.arrayField.onChange(JSON.stringify(updatedArray));

When doing that instead of using real arrays, makeClean works correctly. I'm guessing that this solution won't work on dynamicList though as there's probably fields that cannot be stingified on them.