Ant Design的表单onChange阶段不更新踩坑,以及修改表单值方法
新项目中使用antd-pro框架,所以接下来会写一些关于antd-pro的踩坑
在写项目中,中有一个需求是在某个表单元素变化时,出发表单提交,但是发现一个问题是,将方法绑定onChange
的时候发现此时通过表单方法获取的值还没有更新,不知道这个属于一个bug,还是在这个阶段本来就没有变更表单的values ,所以我是在onChange
绑定的方法中手动将e.target.value
的值赋到表单中,但是不知道有没有其他优雅的解决方式
//radio绑定了切换状态,触发事件
{getFieldDecorator('isEnabled')(
<Radio.Group buttonStyle="solid" onChange={this.changeStatus}>
<Radio.Button >全部</Radio.Button>
<Radio.Button value={1}>启用</Radio.Button>
<Radio.Button value={0}>禁用</Radio.Button>
</Radio.Group>
)}
//方法部分
changeStatus = e => {
const { formValues } = this.state;
const { form } = this.props;
this.setState({
formValues: { ...formValues,status:e.target.value} //手动赋值
});
form.setFieldsValue({status:e.target.value})
this.handleSearch() //调用真正的方法
}
2019/2/17 更新
onChange
阶段为什么表单还没更新
通过查看http://ju.outofmemory.cn/entry/348216这篇文章,我理解到为什么onChange
阶段表单值为什么还没有更新。
这里直接看ant design的源码
onChange
方法,是onCollect
被 bind
后的方法,我们查看源码中的 onCollect
onCollect(name_, action, ...args) {
//onChange方法真正在onCollectCommon中执行
const { name, field, fieldMeta } = this.onCollectCommon(name_, action, args);
const { validate } = fieldMeta;
const newField = {
...field,
dirty: hasRules(validate),
};
//这里进行了最新的值的设置
this.setFields({
[name]: newField,
});
},
下面onCollectCommon
方法的源码
// action实际上是trigger 默认是onChange
onCollectCommon(name, action, args) {
const fieldMeta = this.fieldsStore.getFieldMeta(name);
//下面才是真正onChange方法的执行
if (fieldMeta[action]) {
// onchange getFieldProps中写法
fieldMeta[action](...args);
} else if (fieldMeta.originalProps && fieldMeta.originalProps[action]) {
// onchange getFieldDecorator中的写法
fieldMeta.originalProps[action](...args);
}
// some code...
// onchange同步执行完后再执下面代码,下面的返回并不会受onchange同步执行的影响
return ({ name, field: { ...field, value, touched: true }, fieldMeta });
},
从上面我们可以看出设置最新值setFields
是在onChange
之后,同时我们也可以猜想到,如果在onChange中使用form.setFieldsValue(...)
这样的方法最后会被onCollect
中的setFields
方法重新覆盖而无效,所以如果你想在onChange
阶段修改值的话可以这样
setTimeout(() => {
setFieldsValue({ name: targetValues })
}, 0);
当然在我最上面的代码中,没有使用setTimeout
是因为我不需要修改表单,我只是为了在onChange
阶段获得最新的值并提交表单。
修改表单的值
然而如果你单纯只是为了修改表单的值,而不是为了在onChange
阶段获取最新值的话,不应该使用上面的方法,应该使用官方提供的normalize
,这是专门用来提供修改表单获取的值的方法
...
normalizeAll = (value, prevValue = []) => {
if (value.indexOf('All') >= 0 && prevValue.indexOf('All') < 0) {
return ['All', 'Apple', 'Pear', 'Orange'];
}
if (value.indexOf('All') < 0 && prevValue.indexOf('All') >= 0) {
return [];
}
return value;
};
....
<FormItem>
{this.props.form.getFieldDecorator('fruits', {
normalize: this.normalizeAll,
})(<CheckboxGroup options={options} />)}
</FormItem>