pro-components icon indicating copy to clipboard operation
pro-components copied to clipboard

🐛[BUG] ProTable 使用 ignoreRules + onValuesChange 调用 formeRef.submit() 无法触发request

Open luojinan opened this issue 4 months ago • 1 comments

提问前先看看:

https://github.com/ryanhanwu/How-To-Ask-Questions-The-Smart-Way/blob/main/README-zh_CN.md

🐛 bug 描述

在 ProTable 的 form 配置中使用 ignoreRules: false 且在 onValuesChange 中调用 formRef.current?.submit() ,具备rules的表单触发valuechange 和submit,但是无法按预期触发request。

使用 setTimeoutrequestAnimationFrame 等变通方法来确保表单状态更新后再调用formRef.current?.submit() 提交可以解决。

可能是在触发 onValuesChange 时,表单状态还没有完全更新

📷 复现步骤

  1. 创建一个 ProTable 组件,配置具备rules的search formItem columns配置
  2. ProTable配置 form 属性,1. 设置 ignoreRules 为false使 rules生效, 2. 设置onValuesChange 回调
  3. onValuesChange 回调中直接调用 formRef.current?.submit()
  4. 控制台观察到search表单可以触发valuechange,再触发 submit,但是id表单(具备rules)不会触发后续流程(proTable的request),也不会触发校验,而titile表单(不具备rules)可以正常触发request

可复现代码:

<ProTable
      columns={columns}
      formRef={formRef}
      request={async (params) => {
        console.log('触发request', params);
        return {
          data: [{ id: 1, title: '123' }],
          success: true,
          total: 1,
        };
      }} 
      form={{
        ignoreRules: false,
        onValuesChange: (changedValues: any, allValues: any) => {
          console.log("onValuesChange", changedValues, allValues);
          // ✅ 输入title表单项(没有rules),可以正常在change后触发request
          // ❌ 但是当修改id表单项(具备rules的表单item)时没有触发后续流程(request),可以正常触发valuechange且取到formref以及调用submit
          formRef.current?.submit();
          // 使用settimeout 0 或者使用 Promise.resolve().then() 包裹formref可以解决
        },
      }}
/>
const columns: ProColumns<GithubIssueItem>[] = [
  {
    title: 'id',
    dataIndex: 'id',
  },
  {
    title: 'Title',
    dataIndex: 'title',
    formItemProps: {
      rules: [
        {
          required: true,
          message: 'This field is required',
        },
      ],
    },
  },
];

🏞 期望结果

onValuesChange 回调中直接调用 formRef.current?.submit() 应该能够正常工作,无需使用 setTimeout 或其他变通方法。

💻 复现代码

https://codesandbox.io/p/sandbox/misty-cache-yjdr6m

© 版本信息

  • ProComponents 版本: 2.8.6
  • umi 版本
  • 浏览器环境
  • 开发环境:mac OS

🚑 其他信息

猜测在 src/form/BaseForm/BaseForm.tsx 最接近 Ant Design Form 的地方统一修复:

Image
  1. 在 ProTable 的 form 配置中定义 onValuesChange 回调被传递给 FormRender 组件
  2. FormRender组件将它传递给 BetaSchemaForm 组件
  3. BetaSchemaForm 组件将它传递给 ProForm 组件
  4. ProForm 组件基于 BaseForm 组件
  5. BaseForm 组件最终将它传递给 Ant Design 的 Form 组件

luojinan avatar Aug 18 '25 12:08 luojinan

Hi @luojinan! I'm Dosu and I’m helping the pro-components team.

这个问题的根本原因是 React 和 Ant Design Form 的状态更新是异步的:在 onValuesChange 回调里同步调用 formRef.current?.submit() 时,表单的内部状态还没完全更新,所以校验和 request 没有被正确触发,尤其是带有 rules 的字段。社区常用的解决方法是用 setTimeoutPromise.resolve().then() 等方式延迟 submit,这样可以保证表单状态已经更新完毕,提交时能正确触发校验和 request(相关源码分析)。

目前没有官方文档或最佳实践专门解决这个问题,延迟 submit 是社区公认的 workaround。近期的 PR 和 issue 也没有针对这个行为的修复(相关 PR 还未合并)。建议在 onValuesChange 里用 setTimeoutPromise.resolve().then() 包裹 submit,确保表单状态和校验同步。

如果后续有官方修复或更优方案,建议关注 pro-components 仓库的更新。

To reply, just mention @dosu.


How did I do? Good | Irrelevant | Incorrect | Verbose | Hallucination | Report 🐛 | Other  Chat with Dosu Join Discord Share on X

dosubot[bot] avatar Aug 18 '25 12:08 dosubot[bot]