当前位置: 首页 > 工具软件 > FormDesign > 使用案例 >

使用 react antdesign form 表单动态添加一条数据时造成之前输入框的值丢失

杭泉
2023-12-01

注:可能在做动态 form 表单时直接写一个 form 表单、使用 Form.list 自己不需要写任何变更原来数据结构的逻辑

若是以上情况可以不需要给表单设置值来变更 form 结构、直接在输入完表单之后、取 form 值提交

但很多情况下,业务都会很复杂、比如选择一项值之后需要给其他表单字段设置对应的值、或后台需要类似城市联动组件中,非value值,此处完全依赖 form 表单自身是很难实现的。

以下只存在于复杂逻辑与数据结构时、需要自己存储一份数据对应到 form 中

bug 代码

class example extends React.Component{
    constructor(props) {
        super(props);
        this.state={
            costInfoArr = [{name:""}]
        }
    }

    // 此处做动态添加时、需要先给costInfoArr添加一项、然后通过form.setFieldsValue 设置值;
    addInvInfo = () => {
      // 此时若直接调用此方法会清空之前的值,因为在执行addInvInfo方法时,我们没有把form表单的值同步到costInfoArr中去 costInfoArr还是最开始的初始值[{name:""}]
      const { costInfoArr } = this.state;
      costInfoArr.push({
          name:""
      })
      this.setState({costInfoArr});
      this.formRef.current.setFieldsValue(costInfoArr)
    }

    render(){
      return (
        <Form
          ref={this.formRef}
          initialValues={{
            costInfoArr: costInfoArr,
          }}
          {...this.tableSearchLayout}
        >
          <Form.List name="costInfoArr">
            {fields =>
              fields.map(field => (
                <Form.Item name={[field.name, 'name']}>
                  <Input />
                </Form.Item>
              ))
            }
          </Form.List>
          <Button
            type="dashed"
            style={{ width: '100%', height: 50 }}
            icon={<PlusOutlined />}
            onClick={this.addInvInfo}
          >
            继续添加
          </Button>
        </Form>
      )
    }
}

出现此原因的问题主要是因为 Form 组件本身存储了自身的状态值、需要在 每次执行 form.setFieldsValue(costInfoArr) 时,先把之前输入的 form 中的表单值同步到 costInfoArr 中去

正确代码

class example extends React.Component{
    constructor(props) {
        super(props);
        this.state={
            costInfoArr = [{name:""}]
        }
    }
    addInvInfo = async () => {
      // 在此处之前先调用beforeSetDataSync同步数据
      const { costInfoArr } = this.state;
-       costInfoArr.push({
-           name:""
-       })
-       this.setState({costInfoArr});
+       try {
+         const costInfoArrCopy = await this.beforeSetDataSync(costInfoArr);
+         costInfoArrCopy.push({
+           name:""
+         })
+         this.formRef.current.setFieldsValue(costInfoArrCopy);
+         this.setState({costInfoArr:costInfoArrCopy});
+       } catch (err) {
+         console.error(err)
+       }
    }

+ /**
+  * 同步表单值到存储字段中去
+  * @param {formData} object
+  */
+   beforeSetDataSync = data =>{
+       const formData = JSON.parse(JSON.stringify(data))
+       return new Promise(async (suc, fail) => {
+         try {
+           const values = await this.formRef.current.getFieldsValue()
+           // 此处为业务代码,具体此处如何同步根据业务代码写
+           Object.entries(values).forEach(([key, value]) => {
+             formData[key] = value
+           })
+           suc(formData)
+         } catch (err) {
+           fail(err)
+         }
+       })
+     }
}

还有一种暴力解决方式就是舍弃 Form 组件对自身属性状态管理、直接使用 react 双向绑定、给每个 input 表单加 change 事件、然后变更元数据值

 类似资料: