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

🐛[BUG] ModalForm 子元素的`transform`函数会在初始化时触发且忽视`convertValue`

Open myuanz opened this issue 1 year ago • 9 comments

🐛 bug 描述

根据文档:

transform 发生在提交的时候,一般来说都是吐给后端的存在数据库里的数据。

但是我注意到当我给出initialValues的时候,transform就会在初始化的时候触发,而且会无视convertValue返回的东西

📷 复现步骤

https://codesandbox.io/p/sandbox/modal-biao-dan-forked-dx2fss

打开 Console -> 点击新建表单 -> 观察输出 图片

🏞 期望结果

transform只在提交时运行,或者至少transform会接到convertValue的返回值,而不是只用initialValues

💻 复现代码

https://codesandbox.io/p/sandbox/modal-biao-dan-forked-dx2fss

© 版本信息

  • ProComponents 版本: 2.7.9
  • umi 版本:未使用 umi
  • 浏览器环境:Chrome125.0.6422.60 + Firfox125.0.3
  • 开发环境:与开发环境无关

myuanz avatar May 28 '24 08:05 myuanz

问题是啥?这个逻辑影响了什么?完全没看明白。 而且感觉这个逻辑没问题啊,数据流是这样的 initValues-convertValue-组件内部-transform-提交的值 , 感觉这个数据流是合理的。

fnoopv avatar May 30 '24 13:05 fnoopv

这里的问题是

  1. 没有提交就触发transform函数
  2. 上一步的transform函数的入参不是convertValue的返回

myuanz avatar May 30 '24 13:05 myuanz

这里的问题是

  1. 没有提交就触发transform函数
  2. 上一步的transform函数的入参不是convertValue的返回

纯粹讨论逻辑没意义, 你应该说清楚目前这个逻辑对你的业务产生了什么影响?不符合你这个逻辑会产生什么预期之外的结果?根据现象去讨论问题才有意义。

fnoopv avatar May 30 '24 14:05 fnoopv

当然是因为对业务产生了影响我才注意到这个,但是已经偏离主题太远了。而且文档描述跟逻辑不符本身就是问题,如果文档就是说transform会在初始化时调用一次而且参数是原始值,我只会觉得设计不合理,不会开这个issue。


考虑这样一种情况:我需要填入若干个基因,后端约定用|分割基因,比如"FOXP2|GNB4"这样是两个基因。基因很多又容易写错大小写,于是我用ProFormSelect提供了下拉框,其值是string[]的,因此传入后端时需要transform: v => v.join('|'),编辑时需要从后端convertValue: v => v.split('|')

当我打算编辑时,给出了initialValues期待得到预填充,但初始化时transform就会被调用,其输入还是未经过convertValue的数据库原始表示,是个 string,于是就有了value.join is not a function

  1. 如果transform输入是convertValue过的,那这一次多调用无所谓,反正这是个纯函数
  2. 如果按照文档,transform发生在提交时,那也无所谓,因为提交时transform的输入就是数组

有一些规避方式,我已实施,不必多谈

myuanz avatar May 31 '24 02:05 myuanz

这样看确实存在问题,初始化时调用transform这个操作没啥影响,主要是初始化调用transform时传给transform的指不符合组件值的格式

fnoopv avatar May 31 '24 02:05 fnoopv

当然是因为对业务产生了影响我才注意到这个,但是已经偏离主题太远了。而且文档描述跟逻辑不符本身就是问题,如果文档就是说transform会在初始化时调用一次而且参数是原始值,我只会觉得设计不合理,不会开这个issue。

考虑这样一种情况:我需要填入若干个基因,后端约定用|分割基因,比如"FOXP2|GNB4"这样是两个基因。基因很多又容易写错大小写,于是我用ProFormSelect提供了下拉框,其值是string[]的,因此传入后端时需要transform: v => v.join('|'),编辑时需要从后端convertValue: v => v.split('|')

当我打算编辑时,给出了initialValues期待得到预填充,但初始化时transform就会被调用,其输入还是未经过convertValue的数据库原始表示,是个 string,于是就有了value.join is not a function

  1. 如果transform输入是convertValue过的,那这一次多调用无所谓,反正这是个纯函数
  2. 如果按照文档,transform发生在提交时,那也无所谓,因为提交时transform的输入就是数组

有一些规避方式,我已实施,不必多谈

你好 请问你的规避方式是什么 我也遇到了这个问题,initialValues初始化设置值后,通过convertValue转化成表单希望的值,然后表单提交时,transform不生效了呢

markwei19960204 avatar Aug 15 '24 03:08 markwei19960204

当然是因为对业务产生了影响我才注意到这个,但是已经偏离主题太远了。而且文档描述跟逻辑不符本身就是问题,如果文档就是说transform会在初始化时调用一次而且参数是原始值,我只会觉得设计不合理,不会开这个issue。 考虑这样一种情况:我需要填入若干个基因,后端约定用|分割基因,比如"FOXP2|GNB4"这样是两个基因。基因很多又容易写错大小写,于是我用ProFormSelect提供了下拉框,其值是string[]的,因此传入后端时需要transform: v => v.join('|'),编辑时需要从后端convertValue: v => v.split('|')。 当我打算编辑时,给出了initialValues期待得到预填充,但初始化时transform就会被调用,其输入还是未经过convertValue的数据库原始表示,是个 string,于是就有了value.join is not a function

  1. 如果transform输入是convertValue过的,那这一次多调用无所谓,反正这是个纯函数
  2. 如果按照文档,transform发生在提交时,那也无所谓,因为提交时transform的输入就是数组

有一些规避方式,我已实施,不必多谈

你好 请问你的规避方式是什么 我也遇到了这个问题,initialValues初始化设置值后,通过convertValue转化成表单希望的值,然后表单提交时,transform不生效了呢

我的问题是transform在开始就初始化, 你的问题是transform在提交时不生效, 这两个不一样, 我没有遇到你的问题. 我的问题解决方案是在传入组件之前在其他地方转换数据

myuanz avatar Aug 15 '24 12:08 myuanz

这样看确实存在问题,初始化时调用transform这个操作没啥影响,主要是初始化调用transform时传给transform的指不符合组件值的格式

这样用起来比较繁琐,如果用到了convertValue,transform的逻辑就会比较复杂,需要判断value是否是convert前的数据,如果是的话,还要再处理一次convertValue逻辑。这个设计确实不合理啊。

laketea avatar Nov 21 '24 09:11 laketea

这样看确实存在问题,初始化时调用transform这个操作没啥影响,主要是初始化调用transform时传给transform的指不符合组件值的格式

我也遇到同样的问题,给了ProForm initValues,设置了convertValue和transform,如果不修改目标input直接提交,就会发现transform接收到的是initValues中的原始值而不是convertValue后的值,导致在transform中进行了额外的修改。

lookdczar avatar Aug 19 '25 04:08 lookdczar