ant-design / pro-components

🏆 Use Ant Design like a Pro!
https://pro-components.antdigital.dev
MIT License
4.04k stars 1.29k forks source link

🐛[BUG]DrawerForm,ModalForm,如果绑定上form会导致数据回显问题,且挺严重! #8352

Open codedart2018 opened 2 weeks ago

codedart2018 commented 2 weeks ago

🐛 bug 描述

DrawerForm,ModalForm,如果绑定上form会导致数据回显问题,且挺严重!尝试过关闭窗口form.resetFileds,以及通过open控制form都无法解决此问题!form如果去掉则没有问题,但这个不能取消掉,因为还要做额外的处理

📷 复现步骤

使用 DrawerForm,或ModalForm 绑上form={form}就会出现!

🏞 期望结果

期望绑定form={form}也能正常显示数据!

💻 复现代码

表格编辑提交数据
            <Button
              size="small"
              type="primary"
              onClick={() => {
                let billDate: string[] = [];
                if (row.bill_start_date > 0) {
                  billDate.push(dayjs.unix(row.bill_start_date).format('YYYY-MM-DD'));
                }
                if (row.bill_end_date > 0) {
                  billDate.push(dayjs.unix(row.bill_end_date).format('YYYY-MM-DD'));
                }
                setCurrentRow({
                  id: row.id,
                  department_group_id: row.department_group_id,
                  region_id: row.region_id,
                  insurer_id: row.insurer_id,
                  classification_id: row.classification_id,
                  status: row.status,
                  bill_date: billDate.length === 2 ? billDate : undefined,
                  detail_list: row.detail_list || [],
                });
                setOpen(true);
              }}
            >
              编辑
            </Button>

表单

import React, { FC } from 'react';
import { ProFormDateRangePicker, ProFormRadio, ProFormTreeSelect } from '@ant-design/pro-components';
import { fourToTwentyLW } from '@/constants';
import { Form } from 'antd';
import CusDrawerForm from '@/components/CusDrawerForm';
import { queryDepartmentGroupSelect } from '@/pages/system/policy_rules/department_group/service';
import { queryRegionTree } from '@/pages/system/setting/region/service';
import { queryInsuranceCompanyTree } from '@/pages/system/cooperation/insurance_company/service';
import { queryInsuranceTypeTree } from '@/pages/system/setting/insurance_type/service';
import Ratios from './Ratios';

export type RuleDetailList = {
  commission_ratio: number;
  id: number;
  received_commission_ratio: number;
  remark: string;
};

export type RuleCurrentRow = {
  id?: number;
  department_group_id?: number;
  region_id?: number;
  insurer_id?: number;
  classification_id?: number[];
  bill_date?: string[];
  status?: number;
  detail_list?: RuleDetailList[];
};

export type RuleDrawerFormProps = {
  title: string;
  open: boolean;
  current: RuleCurrentRow | undefined;
  onDone: () => void;
  onSubmit: (values: RuleCurrentRow) => void;
};

const RuleDrawerForm: FC<RuleDrawerFormProps> = (props) => {
  const { title, open, current, onDone, onSubmit } = props;
  const [form] = Form.useForm();

  const ratioAdd = () => {
    const val = form.getFieldValue('detail_list') || [];
    val.push({
      id: 0,
      received_commission_ratio: undefined,
      commission_ratio: undefined,
      remark: '',
      remarks: '',
    });
    form.setFieldValue('detail_list', val);
  };

  const ratioDelete = (index: number) => {
    const val = form.getFieldValue('detail_list');
    if (Array.isArray(val) && val.length > 0) {
      val.splice(index, 1);
      form.setFieldValue('detail_list', val);
      form.validateFields(['detail_list']);
    }
  };

  return (
    <CusDrawerForm<RuleCurrentRow>
      // form={form} //如果去掉则没有问题,但这个不能取消掉,因为还要做额外的处理
      title={current?.id ? `编辑${title}规则` : `添加${title}规则`}
      open={open}
      width={800}
      currentRow={current}
      onSubmit={onSubmit}
      onClose={onDone}
      {...fourToTwentyLW}
    >
      {open && (
        <>
          <ProFormTreeSelect
            name="department_group_id"
            label="组合部门"
            width="md"
            placeholder="请选择组合部门"
            request={async () => {
              const res = await queryDepartmentGroupSelect();
              if (res.code === 0) {
                return res.data.list || [];
              }
              return [];
            }}
            rules={[{ required: true, message: '请选择组合部门' }]}
          />
          <ProFormTreeSelect
            name="region_id"
            label="区域"
            placeholder="请选择区域"
            width="md"
            request={async () => {
              const res = await queryRegionTree();
              if (res.code === 0) {
                return res.data.tree || [];
              }
              return [];
            }}
            rules={[{ required: true, message: '请选择区域' }]}
          />
          <ProFormTreeSelect
            name="insurer_id"
            label="保险公司"
            placeholder="请选择区域"
            width="md"
            request={async () => {
              const res = await queryInsuranceCompanyTree();
              if (res.code === 0) {
                return res.data.tree || [];
              }
              return [];
            }}
            rules={[{ required: true, message: '请选择保险公司' }]}
          />
          <ProFormTreeSelect
            name="classification_id"
            label="规则险种"
            width="md"
            fieldProps={{
              multiple: true,
              // maxTagCount: 'responsive',
              treeDefaultExpandAll: true,
            }}
            placeholder="请选择规则险种"
            request={async () => {
              const res = await queryInsuranceTypeTree();
              if (res.code === 0) {
                return res.data.tree || [];
              }
              return [];
            }}
            rules={[{ required: true, message: '请选择险种' }]}
          />
          <ProFormDateRangePicker
            width="md"
            name="bill_date"
            label="签单起止日期"
            placeholder="请选择签单起止日期"
            rules={[{ required: true, message: '请选择签单起止日期' }]}
          />
          <ProFormRadio.Group
            name="status"
            label="规则状态"
            options={[
              {
                label: '正常',
                value: 1,
              },
              {
                label: '关闭',
                value: 0,
              },
            ]}
          />
          <Ratios name="detail_list" onAdd={ratioAdd} onDelete={ratioDelete} />
        </>
      )}
    </CusDrawerForm>
  );
};

## Ratios组件

import React from 'react'; import Link from 'antd/es/typography/Link'; import { Form, Input, InputNumber } from 'antd'; import '@/style/cus-table.less';

type RatiosProps = { name: string; onAdd?: () => void; onDelete?: (index: number) => void; };

const Ratios = (props: RatiosProps) => { const { name, onAdd, onDelete } = props;

return (

{(fields) => { if (fields.length === 0) { return ( ); } return fields.map((field) => { return ( ); }); }}
ID 佣金应收比例(%) 佣金应付比例(%) 备注 新增
暂无数据
onDelete?.(field.key)}> 删除

); };

export default Ratios;

export default RuleDrawerForm;

视频录屏情况

https://github.com/ant-design/pro-components/assets/12706830/226cc922-51ed-4274-a887-ee44e1517d28

https://github.com/ant-design/pro-components/assets/12706830/455bd6f4-c3ba-463d-a6a0-e0ddeb775268

取消掉form情况

https://github.com/ant-design/pro-components/assets/12706830/4a86f82d-7e47-4c5d-bf90-2e928e1b072e

通过
<Form.Item shouldUpdate noStyle>
            {({ getFieldValue }) => {

去拿数据打印出来,明显看到是上一次的数据,非本次提交过来的数据。

相关有人提的bug

https://github.com/ant-design/pro-components/issues/7925

@Gzbox 你有解决掉这个情况吗?

© 版本信息

🚑 其他信息

gululululuu commented 2 weeks ago

form取值是undefined呀,有具体点的代码吗

codedart2018 commented 5 days ago

form取值是undefined呀,有具体点的代码吗

import React, { FC, useEffect } from 'react';
import { ProFormDateRangePicker, ProFormRadio, ProFormTreeSelect } from '@ant-design/pro-components';
import { fourToTwentyLW } from '@/constants';
import { Form } from 'antd';
import CusDrawerForm from '@/components/CusDrawerForm';
import { queryDepartmentGroupSelect } from '@/pages/system/policy_rules/department_group/service';
import { queryRegionTree } from '@/pages/system/setting/region/service';
import { queryInsuranceCompanyTree } from '@/pages/system/cooperation/insurance_company/service';
import { queryInsuranceTypeTree } from '@/pages/system/setting/insurance_type/service';
import Ratios from './Ratios';
import { RuleCurrentRow, RuleDrawerFormProps } from './types';

const RuleDrawerForm: FC<RuleDrawerFormProps> = (props) => {
  const { title, open, current, onDone, onSubmit } = props;
  const [form] = Form.useForm();

  const ratioAdd = () => {
    const val = form.getFieldValue('detail_list') || [];
    val.push({
      id: 0,
      received_ratio: undefined,
      ratio: undefined,
      remark: '',
      remarks: '',
    });
    form.setFieldValue('detail_list', val);
  };

  const ratioDelete = (index: number) => {
    const val = form.getFieldValue('detail_list');
    if (Array.isArray(val) && val.length > 0) {
      val.splice(index, 1);
      form.setFieldValue('detail_list', val);
      form.validateFields(['detail_list']);
    }
  };

  useEffect(() => {
    if (open) {
      form.resetFields();
    }
  }, [open]);

  return (
    <CusDrawerForm<RuleCurrentRow>
      form={form}
      title={current?.id ? `编辑${title}规则` : `添加${title}规则`}
      open={open}
      width={800}
      // request={() => {
      // 如果用request套上form会导致数据二次还是上一次的数据,使用 initialValues来给值,同时effect强制干掉
      //   return Promise.resolve({
      //     ...current,
      //   });
      // }}
      initialValues={current}
      onSubmit={onSubmit}
      onClose={onDone}
      {...fourToTwentyLW}
    >
      {open && (
        <>
          <ProFormTreeSelect
            name="department_group_id"
            label="组合部门"
            width="md"
            placeholder="请选择组合部门"
            request={async () => {
              const res = await queryDepartmentGroupSelect();
              if (res.code === 0) {
                return res.data.list || [];
              }
              return [];
            }}
            rules={[{ required: true, message: '请选择组合部门' }]}
          />
          <ProFormTreeSelect
            name="region_id"
            label="区域"
            placeholder="请选择区域"
            width="md"
            request={async () => {
              const res = await queryRegionTree();
              if (res.code === 0) {
                return res.data.tree || [];
              }
              return [];
            }}
            rules={[{ required: true, message: '请选择区域' }]}
          />
          <ProFormTreeSelect
            name="insurer_id"
            label="保险公司"
            placeholder="请选择区域"
            width="md"
            request={async () => {
              const res = await queryInsuranceCompanyTree();
              if (res.code === 0) {
                return res.data.tree || [];
              }
              return [];
            }}
            rules={[{ required: true, message: '请选择保险公司' }]}
          />
          <ProFormTreeSelect
            name="classification_id"
            label="规则险种"
            width="md"
            fieldProps={{
              multiple: true,
              // maxTagCount: 'responsive',
              treeDefaultExpandAll: true,
            }}
            placeholder="请选择规则险种"
            request={async () => {
              const res = await queryInsuranceTypeTree();
              if (res.code === 0) {
                return res.data.tree || [];
              }
              return [];
            }}
            rules={[{ required: true, message: '请选择险种' }]}
          />
          <ProFormDateRangePicker
            width="md"
            name="bill_date"
            label="签单起止日期"
            placeholder="请选择签单起止日期"
            rules={[{ required: true, message: '请选择签单起止日期' }]}
          />
          <ProFormRadio.Group
            name="status"
            label="规则状态"
            options={[
              {
                label: '正常',
                value: 1,
              },
              {
                label: '关闭',
                value: 0,
              },
            ]}
          />
          <Ratios name="detail_list" onAdd={ratioAdd} onDelete={ratioDelete} />
        </>
      )}
    </CusDrawerForm>
  );
};

export default RuleDrawerForm;

我的业务代码,使用 request 无论我怎么做都会有问题。所以我把request注释了。 使用的initValues 但是如果不在useEffect里进行一次resetFields也会是有问题的!反正这个bug很无语。