【问题标题】:React-Final-Form: Set initialValues from props, form state resets on props changeReact-Final-Form:从 props 设置 initialValues,在 props 更改时重置表单状态
【发布时间】:2019-02-11 16:46:35
【问题描述】:

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

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

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

请参阅此代码框以获取示例:https://codesandbox.io/s/jn69xql7y3:

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

【问题讨论】:

    标签: react-final-form final-form


    【解决方案1】:

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

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

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

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

    这意味着如果你在渲染中创建一个新对象,即使是相同的,当某些状态发生变化时,整个表单都会重置,渲染函数重新运行,并为@创建一个具有新引用的新对象987654326@.

    为了解决一般问题,如果你只是想关闭表单重置,我所做的只是将我的 initialState 移动到一个变量中,它永远不会改变,这样它在每次渲染时都是相同的引用因此,默认行为似乎总是与 final-form 相同。我希望配置能够完全关闭这种重新初始化行为,但我在文档中找不到。

    但是,如果您确实想要这个,但需要修改它,可以使用initialValuesEqual 属性(docs here)配置比较行为,例如对initialValues 对象进行深度比较。

    您还可以使用 keepDirtyOnReinitialize 属性仅重置表单中未被触及的部分。

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

    【讨论】:

      【解决方案2】:

      除了@davnicwil 提到的,我的解决方案是useMemo() func 组件中的钩子:

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

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

      【讨论】:

      • 这也适用于我。尽管我认为这最终可能会在图书馆内部发生。因为我认为在第一次渲染后不应该使用 initialValue。
      【解决方案3】:

      另一种解决方案是使用 react-final-form Form prop initialValuesEqual={() =&gt; true}

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

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

      【讨论】:

        猜你喜欢
        • 2020-07-05
        • 2015-12-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-03-29
        相关资源
        最近更新 更多