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

Update gets triggered on render with initialValues #26

Open
AdamGerthel opened this issue Dec 19, 2018 · 13 comments
Open

Update gets triggered on render with initialValues #26

AdamGerthel opened this issue Dec 19, 2018 · 13 comments

Comments

@AdamGerthel
Copy link

AdamGerthel commented Dec 19, 2018

Are you submitting a bug report or a feature request?

Not sure if it's a bug or a if it works as intended

What is the current behavior?

Updates are triggered once when then the form is rendered, i.e. even though no changes have been made to the form values.

See https://codesandbox.io/s/0ml4k745x0

What is the expected behavior?

I would expect updates to be triggered only on updates, not by the initial values.

What's your environment?

    "react": "^16.6.3",
    "react-dom": "^16.6.3",
    "react-final-form": "^4.0.2",
    "final-form": "^4.11.0",
    "final-form-calculate": "^1.3.0"
@Babbz75
Copy link

Babbz75 commented Mar 14, 2019

Did anyone find a work around for this?

@Soundvessel
Copy link

Soundvessel commented Mar 14, 2019

Perhaps you can use the field's pristine prop to watch for a change on that specific field? Pristine will respect initialValues.
https://github.com/final-form/final-form#pristine-boolean

Edit: Although I don't see the API able to get meta of the field?

@nik-lampe
Copy link

Interesting.
This does not happen, when you specify the field as a regex.
And, it gets triggered, but it seems that the changes won't be applied to the values.

Came across this, because I'm looking for a way to do a initial calculation with the initial values

@Soundvessel
Copy link

Just a thought but is there a chance the form is rendered before the initial values are available and adding them to an existing form could be the culprit? This could be confirmed either with the React profiler tool or logic to prevent render until you have the data for initialValues ready?

@Dragomir-Ivanov
Copy link

I think that this is valid behavior. I am using exactly this functionality, in order to calculate additional fields, based on initial ones.

@AdamGerthel
Copy link
Author

@Dragomir-Ivanov Right, but just because use exploit that fact that it functions like this doesn't mean that it's expected behaviour.

I personally would expect an "update" hook to run on updates only, not creation/initialisation. I mean, that could easily be handled outside of Final Form entirely.

I do think that this is a an issue that would potentially cause a new major release since it might break a lot of existing uses of this plugin.

@AdamGerthel
Copy link
Author

Just a thought but is there a chance the form is rendered before the initial values are available and adding them to an existing form could be the culprit? This could be confirmed either with the React profiler tool or logic to prevent render until you have the data for initialValues ready?

@Soundvessel If you look at my sandbox sample in the original post, you'll see that the value is there from the start.

@Dragomir-Ivanov
Copy link

@AdamGerthel You may be right. For the time being I guess you can fork your own Decorator, final-form-calculate is rather small, until this issue is settled.

@cordial
Copy link

cordial commented May 18, 2021

Is there any way round this? I load my initial values from a DB and this sets off an update which can make the values different from the DB values.

@leonardopolly
Copy link

@cordial, I got to work around this by wrapping createDecorator function in my own really small decorator that returns the original decorator called with form as its argument. In the updates property you can now access form and check if it is pristine. If it is, simply return an empty object :)

Instead of writing

const myDecorator = createDecorator({
  field: 'fieldA',
  updates: {
    b: (fieldAValue, allValues) => { 
      //your calculation 
    }
  }
});

you can write

const myDecorator = form => createDecorator({
  field: 'fieldA',
  updates: form.getState().pristine? {} : {
    b: (fieldAValue, allValues) => { 
      //your calculation 
    }
  }
})(form)

@dozen1488
Copy link

@cordial, I got to work around this by wrapping createDecorator function in my own really small decorator that returns the original decorator called with form as its argument. In the updates property you can now access form and check if it is pristine. If it is, simply return an empty object :)

Instead of writing

const myDecorator = createDecorator({
  field: 'fieldA',
  updates: {
    b: (fieldAValue, allValues) => { 
      //your calculation 
    }
  }
});

you can write

const myDecorator = form => createDecorator({
  field: 'fieldA',
  updates: form.getState().pristine? {} : {
    b: (fieldAValue, allValues) => { 
      //your calculation 
    }
  }
})(form)

How can you get access to the form state, when you need to set decorator to render form, and only inside form render callback you can get form state.

@leonardopolly
Copy link

@dozen1488

How can you get access to the form state, when you need to set decorator to render form, and only inside form render callback you can get form state.

According to the official docs, a decorator is a function that receives the form api as a parameter, subscribes to it, making changes as the state changes, and returns an Unsubscribe function.
https://final-form.org/docs/final-form/types/Decorator

So when you create a decorator using the createDecorator function, that function call is returning another function in the shape of formApi => { // whatever change you told the decorator to make }

@MrBlackRain
Copy link

Sorry for necroposting.
I recently stumbled across the same problem.
@leonardopolly suggestion didn't work for me in case when updates is a function, not an object.
So I just put an if statement inside a function, like this

const myDecorator = form => createDecorator({
  field: 'fieldA',
  updates: (fieldAValue, fieldName, allValues, prevAllValues) => { 
      if (form.getState().pristine) return {}
      //your calculation 
    }
  }
})(form)

Maybe, it will be useful for somebody.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

9 participants