React-Final-Form: Set initialValues from props, form state resets on props change

怎甘沉沦 提交于 2021-02-20 11:24:48

问题


I have a component, that takes a balance prop, and this balance prop can change over time.

I then have a React Final Form to send a transaction, with usual fields amount to send, receiver... And in my validate, I just check that the user has enough balance to send the transaction.

However, if my balance changes when the user is inputting something, then the whole form resets. How would you only reset part of the form state?

See this codesandbox for an example: https://codesandbox.io/s/jn69xql7y3:

  • input something
  • wait 5s
  • see that the form state is blank again

回答1:


I just ran into this issue with react-final-form where the form completely resets when any state change happens in a wrapping component.

The problem is here (from your codesandbox)

<Form
  initialValues={{ amount: 0, balance }} <-- creates a new object on every render

The problem is that when initialValues changes the entire form reinitialises. By default, whatever you pass to initialValues is compared against the previous one using shallow equals, i.e. comparing reference.

This means that if you create a new object in the render, even if it's the same, the entire form resets when some state changes, the render function re-runs, and a new object with a new reference is created for initialValues.

To solve the general problem, if you just want to turn off the form resetting, what I've done is just move my initialState, which never changes, out to a variable so that it's the same reference on every render and therefore always appears to be the same to final-form with the default behaviour. I would prefer a configuration to actually completely turn off this reinitialisation behaviour, but I can't find one in the docs.

However if you actually want this, but need to modify it, the comparison behaviour can be configured using the initialValuesEqual prop (docs here), to do a deep comparison on the initialValues object for example.

You can also use the keepDirtyOnReinitialize prop to only reset the parts of your form that haven't been touched.

I would guess some combination of the above might solve your usecase, depending on the exact UX you need.




回答2:


Adding onto what @davnicwil mentioned, my solution is useMemo() hook in func components:

const initialValues = useMemo(() => ({ amount: 0, balance }), [])

By using useMemo it creates only 1 object during the life of the component and subsequent re-renders don't cause initialValues to overwrite the form values.




回答3:


Another solution is to use react-final-form Form prop initialValuesEqual={() => true}

<Form initialValues={{ amount: 0, balance }} initialValuesEqual={() => true} .../>

ref: https://github.com/final-form/react-final-form/issues/246



来源:https://stackoverflow.com/questions/54635276/react-final-form-set-initialvalues-from-props-form-state-resets-on-props-chang

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!