antd将嵌套表单的对话框组件化,实现编辑功能

问题

当使用对话框提交修改表单时,需要在输入框 Input 显示需要修改的数据,但使用 value 绑定对应数据,并未生效,具体代码如下:

function YwkclbEdit (props) {
	....
	const editData = props.data;
	....
}
<Form.Item
  name='hzxm'
  label='患者姓名'
>
  <Input placeholder="请输入患者姓名"
         value={editData.name} />
</Form.Item>

结果,在控制台输出数据时,可以发现 editData 是有对应数据的,但对话框却没有显示对应数据。
在这里插入图片描述

测试一

如果不是 Input 组件和数据的问题,那么应该是嵌套了 Form 表单引起的。

因此,单独测试下,将 Input 单独提取出表单外。

<Input placeholder="请输入患者ID" value={editData.name} />
<Form
  ref={ywkcEditForm}
  name='ywkcEditForm'
  size="small"
  {...layout}
>
  <Row justify="start" className="ywgllbAddFormItem">
    <Col span="24" key="a1">
      <Form.Item
        name='hzid'
        label='患者ID'
      >
        <Input placeholder="请输入患者ID" value={editData.name} />
      </Form.Item>
    </Col>
  </Row>

结果如下,的确是嵌套表单引起的。

在这里插入图片描述

重新回顾Form组件相关内容,发现:

被设置了 name 属性的 Form.Item 包装的控件,表单控件会自动添加 value(或 valuePropName 指定的其他属性) onChange(或 trigger 指定的其他属性),数据同步将被 Form 接管,这会导致以下结果:

1、你不再需要也不应该用 onChange 来做数据收集同步(你可以使用 Form 的 onValuesChange),但还是可以继续监听 onChange 事件。

2、你不能用控件的 value 或 defaultValue 等属性来设置表单域的值,默认值可以用 Form 里的 initialValues 来设置。注意 initialValues 不能被 setState 动态更新,你需要用 setFieldsValue 来更新。

3、你不应该用 setState,可以使用 form.setFieldsValue 来动态改变表单值。
在这里插入图片描述

测试二

从文档解释可以发现错误在于数据同步被Form接管,因此,要将需要同步的数据交给Form使用(ps.虽然有除去name属性的方法,但先且按文档说明使用):

function YwkclbEdit (props) {
  const ywkcEditForm = React.createRef();
  const editData = props.data;
  ywkcEditForm.current.setFieldsValue({  // 错误处
    hzid: editData.name
  })
  
  ...
  
  <Form
    ref={ywkcEditForm}
    name='ywkcEditForm'
    size="small"
    {...layout}
  >
    <Row justify="start" className="ywgllbAddFormItem">
      <Col span="24" key="a1">
        <Form.Item
          name='hzid'
          label='患者ID'
        >
          <Input placeholder="请输入患者ID"/>
        </Form.Item>
      </Col>
    </Row>

	...
}

想法很美好,现实很骨感,直接出现错误:

TypeError: Cannot read property ‘setFieldsValue’ of null

没有对应属性,容易发现是表单创建失败

继续查看文档,由于我们使用的函数组件,对应表单数据交互应该使用

Form.useform

在这里插入图片描述

测试三

根据文档提示,合理使用,成功实现数据交互。

function YwkclbEdit (props) {
  const [ ywkcEditForm ] = Form.useForm(); // useForm() 返回的是表单数组,因此需要[]
  const editData = props.data;
  ywkcEditForm.setFieldsValue({
    hzid : editData.name,
 })
 
 ...
<Form
  form={ywkcEditForm}  // 修改处
  name='ywkcEditForm'
  size="small"
  {...layout}
>
  <Row justify="start" className="ywgllbAddFormItem">
    <Col span="24" key="a1">
      <Form.Item
        name='hzid'
        label='患者ID'
      >
        <Input placeholder="请输入患者ID"/>
      </Form.Item>
    </Col>
  </Row>
 
 ...
}

演示效果如下,但是却出现了

Warning: Instance created by useForm is not connected to any Form element. Forget to pass form prop?
Uncaught SyntaxError: Unexpected token ‘<’

在这里插入图片描述

测试四

详细查看文档小字部分,发现在 Modal 中调用 Form 时,因为Modal还初始化,导致 Form 实例没有绑定表单,根据文档给 Modal 添加forceRender 属性,可以解决该警告。

在这里插入图片描述
在为Modal添加了 forecRender 属性后,选择任意数据后,会发现如下警告:

Warning: Cannot update during an existing state transition (such as within render). Render methods should be a pure function of props and state.

报错是由于引用的子组件通过props进行传递,传递的过程中 Modal 实际上已经处于render阶段了 ,render 还没结束时将数据传入会触发state 改变,在这个阶段如果你再改变这个state值的话就会报这个错。因此,不要在render的时候改变state就可以解决问题。

考虑到父组件传入的数据为只读,又需要通过异步操作避免render时本地state变动的问题,要避免直接传入父组件数据来为本地state赋值,同时,考虑到多用户情况,列表数据可能已经被修改,应该采用axios请求服务器发送对应ID的数据,保证数据实时性,代码如下:

  // 子组件通过获取父组件传入的editId,向服务器申请对应数据并赋值
  const searchById = (id) => {
    console.log(id);
    Conn.getYwkcById(id)
      .then(res => {
        ywkcEditForm.setFieldsValue({hzid: res.hzid, ywmc: res.ywmc,ywpp: res.ywpp, ywsl: res.ywsl})
      })
      .catch((err) => {
        console.log(err);
      })
  };
  
  searchById(props.editId);

结果很成功,先前出现的警告消失了,而且数据也能顺利交互。

总结

测试到此告一段落了,关于React、antd如何将嵌套表单的对话框组件化、实现数据交互作出了实践测试。

另外,Antd的说明文档非常重要的,遇到问题往往可以先查看说明文档,只要找到了对应的错误,往往会有成熟的解决方案。

引用

https://www.cnblogs.com/banyouxia/p/13188698.html

https://blog.csdn.net/estherlxy/article/details/106145389

https://ant.design/components/modal-cn/

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,这里是使用react hooks实现类似Antd对话框Modal组件的示例代码: ```jsx import React, { useState } from "react"; import ReactDOM from "react-dom"; const Modal = ({ title, visible, onOk, onCancel, children }) => { const [isModalVisible, setIsModalVisible] = useState(visible); const handleOk = () => { setIsModalVisible(false); onOk && onOk(); }; const handleCancel = () => { setIsModalVisible(false); onCancel && onCancel(); }; return isModalVisible ? ( <div className="modal-wrapper"> <div className="modal"> <div className="modal-header"> <h3 className="modal-title">{title}</h3> </div> <div className="modal-content">{children}</div> <div className="modal-footer"> <button className="modal-btn modal-btn-ok" onClick={handleOk}> OK </button> <button className="modal-btn modal-btn-cancel" onClick={handleCancel}> Cancel </button> </div> </div> </div> ) : null; }; const App = () => { const [visible, setVisible] = useState(false); const showModal = () => { setVisible(true); }; const handleOk = () => { console.log("OK button clicked"); }; const handleCancel = () => { console.log("Cancel button clicked"); }; return ( <div> <button onClick={showModal}>Show Modal</button> <Modal title="Modal Title" visible={visible} onOk={handleOk} onCancel={handleCancel} > <p>Modal Content</p> </Modal> </div> ); }; ReactDOM.render(<App />, document.getElementById("root")); ``` 这个示例代码,我们首先定义了一个`Modal`组件,它包含了标题、内容区和底部按钮。在组件内部,我们使用`useState`来管理对话框的可见状态,并且定义了`handleOk`和`handleCancel`函数来处理点击ok和cancel按钮的事件。最后,我们在`return`语句根据对话框的可见状态来渲染对话框。 在`App`组件,我们使用`useState`来管理对话框的可见状态,并且定义了`showModal`、`handleOk`和`handleCancel`函数来处理对话框的显示和按钮的点击事件。最后,我们在`return`语句渲染一个按钮和一个对话框。 这个示例代码,我们实现了一个简单的对话框Modal组件,它支持title、visible、onOk和onCancel属性Prop。如果你需要更多的功能,可以根据自己的需求进行扩展。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值