Ant Design的表单onChange阶段不更新踩坑,以及修改表单值方法

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方法,是onCollectbind 后的方法,我们查看源码中的 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>

你可能感兴趣的:(前端笔记,解决问题,ant-design)