8

我有一个组件,它需要一个balance道具,这个平衡道具会随着时间而改变。

然后我有一个 React Final Form 来发送交易,通常的字段是要发送的金额,接收者......在我的 中validate,我只是检查用户是否有足够的余额来发送交易。

但是,如果在用户输入内容时我的余额发生了变化,那么整个表单都会重置。你将如何只重置表单状态的一部分?

有关示例,请参见此代码框:https ://codesandbox.io/s/jn69xql7y3 :

  • 输入一些东西
  • 等待 5 秒
  • 看到表单状态又是空白
4

3 回答 3

12

我刚刚遇到了这个问题,react-final-form当包装组件中发生任何状态更改时,表单会完全重置。

问题就在这里(来自您的代码框)

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

问题是当initialValues更改时整个表单会重新初始化。默认情况下,您传递给的任何内容都将使用浅的 equalsinitialValues与前一个进行比较,即比较参考。

这意味着如果您在渲染中创建一个新对象,即使它是相同的,当某些状态更改时,整个表单都会重置,渲染函数重新运行,并为initialValues.

为了解决一般问题,如果您只想关闭表单重置,我所做的只是将 myinitialState永远不会改变的变量移到一个变量中,以便它在每个渲染上都是相同的引用,因此似乎总是与具有默认行为的最终形式相同。我希望配置能够完全关闭这种重新初始化行为,但我在文档中找不到。

但是,如果您确实想要这个,但需要修改它,可以使用initialValuesEqual道具(此处的文档initialValues)配置比较行为,例如对对象进行深度比较。

您还可以使用该keepDirtyOnReinitialize道具仅重置尚未触及的表单部分。

我猜上述的一些组合可能会解决您的用例,具体取决于您需要的确切用户体验。

于 2019-10-25T15:30:10.850 回答
10

除了@davnicwil 提到的内容之外,我的解决方案是useMemo()挂钩 func 组件:

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

通过使用useMemo它在组件的生命周期内仅创建 1 个对象,并且后续重新渲染不会导致 initialValues 覆盖表单值。

于 2020-02-29T05:19:18.157 回答
4

另一种解决方案是使用 react-final-form Form propinitialValuesEqual={() => true}

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

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

于 2020-02-29T05:21:23.613 回答