Antd Modal 关闭以后, 重置Form表单数据

7,410 阅读2分钟

做后台管理的时候, 常常会在弹窗里套一个表单

image

大部分情况下都会想在弹窗关闭的时候, 重置表单的数据

通用的解决方案

就是字面的意思, “弹窗关闭以后重置表单就好了”

<Modal afterClose={() => form.resetFields()}>
  <Form >
</Modal>

不过之前我是不知道afterClose这个属性的

我会根据visible的值来判断弹窗是否关闭

如果用 class 组件, 可以在 componentDidUpdate做这个判断

componentDidUpdate(preProps) {
  if (prevProps.visible && !this.props.visible) {
    this.props.form.resetFiles()
  }
}

如果是用 hooks, 我会粗暴一点, 直接

React.useEffect(() => {
  if (!visible) {
    form.resetFields()
  }
}, [visible])

destroyOnClose

Modal 有一个 destroyOnClose 属性, 官方的解释是

关闭时销毁 Modal 里的子元素

很多人以为加了这个就行了, 但是得分情况讨论

如果用的是Antd 4

参考它的文档

<Modal /> 和 Form 一起配合使用时,设置 destroyOnClose 也不会在 Modal 关闭时销毁表单字段数据,需要设置 <Form preserve={false} />

也就是说, 像下面👇这样同时加上preserve={false}才行

<Modal destroyOnClose>
  <Form preserve={false} >
</Modal>

可以参考这个issue, 里面有更多的讨论 github.com/ant-design/…

如果用的是Antd 3

很多时候确实是加了 destroyOnClose , 就可以了

但是如果使用自定义的表单控件, 会发现v3的官网有这么一段提示:

3x.ant.design/components/…

自定义或第三方的表单控件,也可以与 Form 组件一起使用。只要该组件遵循以下的约定:

  • 提供受控属性 value 或其它与 valuePropName 的值同名的属性。
  • 提供 onChange 事件或 trigger 的值同名的事件。
  • 支持 ref:
    • React@16.3.0 之前只有 Class 组件支持。
    • React@16.3.0 及之后可以通过 forwardRef 添加 ref 支持。(示例

第三点, 值得引起注意, 要支持ref

也就是说, 如果用函数式组件写了自定义的表单控件, 那么要注意 forwardRef 才行

antd 3 的表单底层用的是rc-form(antd 4用的是rc-field-form), 经过一番搜索, 发现了一个有趣的PR:

github.com/react-compo…

点进这个链接, 它的commit信息是

feat: getFieldDecorator support no ref component

通过查看这一楼层的评论和代码

github.com/react-compo…

可以发现, rc-form对于每一个field, 都会依靠ref来判断表单控件是否unmount, 如果unmount的话就进行重置表单字段值的操作

那么之前说的要支持ref, 就可以解释了

所以, 最后强调一下, 如果使用antd3(准确地说是3.26.20及以前的版本)并且用了function component来封装自定义的表单组件, 又要用destroyOnClose的话, 要forwardRef

其他

有一点我感觉比较奇怪, antd4 <Form /> perserve 的默认值是 true , 但是底层用的rc-field-form 的默认值却是 false

在对应的 PR 里问了一下相关人员, 但是也没有得出很确切的结论. 我认为默认 false 会更符合直觉一些