使用 validateFields
,点击保存的时候控制台会打印警告,但是表单中无飘红提示。
问题背景
写了一个表单校验,用来验证输入的字符串是否全为空格。当我点击保存的时候(调用 validateFields
方法),在控制台提示了如下警告:
代码是这样的:
<FormItem
label="规格"
className="contact-detail-info-form-item"
{...formItemLayout}
>
{
getFieldDecorator('specification', {
initialValue: data.specification,
rules: [
{
required: true,
message: '请输入规格',
},
{
validator: (rule, value, callback) => {
/* 注意看这里!!! */
if (value.length && !value.trim().length) {
callback('规格文案不能全为空格');
}
else {
callback();
}
}
}
],
})(<Input
allowClear
className="custom-input"
placeholder="请输入规格"
/>)
}
</FormItem>
解决方案
通过查阅相关问题发现,只要在 validator
方法的判断中加上对于 value
值本身的判断就能解决问题。像下面这样:
<FormItem
label="规格"
className="contact-detail-info-form-item"
{...formItemLayout}
>
{
getFieldDecorator('specification', {
initialValue: data.specification,
rules: [
{
required: true,
message: '请输入规格',
},
{
validator: (rule, value, callback) => {
/* 注意看这里!!!加上了 value 的判断 */
if (value && !value.trim().length) {
callback('规格文案不能全为空格');
}
else {
callback();
}
}
}
],
})(<Input
allowClear
className="custom-input"
placeholder="请输入规格"
/>)
}
</FormItem>
加上对于 value 的判断后再去校验就出现飘红提示了。
问题原因分析
虽然问题解决了,但是如此怪异的问题我还是得弄清楚原因才行,不然再次遇到同类问题的时候可能不知道该怎么处理。
对比了一下前后的区别,发现将 value.length
改成 value
的区别在于 value.length
这个表达式本身就可能报错。比如当 value
为 undefined
时。
而 validator
非常强调的一件事就是 callback
方法必须要被执行。而当 value
为 undefined
时,程序在运行时就会报错,导致 callback
方法没有被调用。
而程序报错没有却没有在控制台看到错误打印的原因是可能是因为 Antd Form validator 外部使用了 try...catch
对错误进行捕获。
实践出真知。
为了验证这个猜想的正确性,我在代码代码中添加了如下的打印:
// 校验空格
const validateBlank = (rule: any, value: string, callback: (str?: string) => void) => {
console.log(1);
if (value.length && !value.trim().length) {
console.log(2);
callback('规格文案不能全为空格');
}
else {
console.log(3);
callback();
}
};
然后点击保存。发现在控制台中仅仅打印了 1
。这样的验证结果是符合我的猜想的。为了更加坚定这个结论,我查阅了 Antd 文档。
知子莫如父。
我在 Antd 文档中发现了这样一个FAQ:自定义 validator 没有效果.
描述如下:
这是由于你的
validator
有错误导致callback
没有执行到。你可以选择通过async
返回一个 promise 或者使用try...catch
进行错误捕获:
这段描述的第一句话就正中下怀啊。官方提供的解决方案是在 validator
方法内部使用 try...catch
进行错误捕获,然后在 catch
语句中调用一下 callback
。详情参见上方的文档。