遇到的问题:我们经常用用 antd 的 form 中的setFieldsValue来给表单设置值,以实现表单的回显;但是有时并不那么顺利,我个人也在写代码或者改别人代码bug中遇到过类似的问题,明明设置成功了,却没有回显。
以下是从发现问题到解决问题的过程

useEffect(() => {
if (statusId) {
form.setFieldsValue({flowStatus: 1});
}
}, [statusId]);
但是这个select框没有任何变化;---(此时怀疑数据格式问题)
过程1:怀疑数据格式
于是更改了数据格式:
{flowStatus: 1} 变为 {flowStatus: '1'};
即,将数字转化为字符串,发现仍然不能回显。---(此时怀疑是值没有被赋值上去)
过程2: 怀疑没有赋值
为了验证值有没有被赋值,打印一下看看
useEffect(() => {
if (statusId) {
form.setFieldsValue({flowStatus: 1});
console.log('flowStatus', form.getFieldValue('flowStatus'))
}
}, [statusId]);

可以看到flowStatus 有值但是仍然没有回显;这就奇怪了,命名设置了值,值也拿到了,为什么没有回显;antd出bug了。---(难道antd出bug了?)
过程3: 再度思考--万念俱灰
会不会有其他的api也改变了我赋的值,那么这些api有没有出现。form.resetFields();也会改变这个值,于是去看哪里用到了这个api; 于是我找到了这块代码
useEffect(() => {
if (formConfigListValues.length === 0) { // todo 不能用这个判断
form.resetFields();
}
}, [formConfigListValues]);
看到这块代码,是这块问题的概率大概有90%; 打印验证一下

结论:果然再赋值之后又被重置,导致了没有回显;
过程4:回显成功,有点瑕疵
找到问题了,所以应该如何写呢。以下是我的代码;
useEffect(() => {
if (formConfigListValues.length === 0) {
form.resetFields();
if (statusId) {
form.setFieldsValue({flowStatus: 1});
}
}
}, [formConfigListValues, statusId]);
我的个人思考是
- 1:resetFields这个api用的次数很少,基本就用一次,不如放在此处的useEffect里边;
- 2:将setFieldsValue和resetFields放在一块,方便后期的维护,降低其他人修改代码的成本;
但是这种是 错误 的;因为formConfigListValues在每次操作完表单时候要走一遍,但是导致了,审批状态一直不会变(也就是操作审核状态失效); 运行结果:

最后的结果:云开雾散,水落石出,真相大白
最后的代码如下:
useEffect(() => {
if (formConfigListValues.length === 0) {
form.resetFields();
}
}, [formConfigListValues]);
useEffect(() => {
if (statusId) {
form.setFieldsValue({flowStatus: 1});
}
}, [statusId]);

最终思考 当我们在Hooks组件中使用Antd表单form的setFieldsValue,时要有注意,
- 1: 是否数据格式错误(value应该是字符串还是数字)
- 2: 在数据格式正确但是没有回显的,要想到还有哪些也可能影响设置值(如:resetFields)
- 3: 在hooks中使用setFieldsValue,还要注意写代码的顺序和层级结构(如:新加的setFieldsValue到底放在里边还是外边,放到外边的话是否要注意,要放在resetFields所在useEffect的下边)。