Problem description

An error occurs when the Ant Design component library uses a Form component in the Modal component

Github.com has plenty of descriptions of the problem. Such as

  • Github.com/ant-design/…
  • Github.com/ant-design/…

A lot of people respond, and the main method is to add a forceRender attribute to Modal but it doesn’t work at all. Other methods were tried, but to no avail.

Question why

Ant Design uses Form forms in Modal and still gets a warning when it fetches the Form object via form.useform () and mounts it to the specified Form Form, because Ant Design’s Modal component is created before the Form Form, Therefore, when the page initializes, the form object will not find a form to associate with, hence the warning.

The solution

Using useEffect, you can add props. Visible to trigger side effects based on dependencies.

UseEffect Adds props. Visible triggers side effects based on certain dependency conditions. 2

code


import { Modal, Form, Input, Button, Checkbox } from 'antd';
import React, { useEffect, useRef } from 'react';

const UserModel = (props: any) = > {
  const [form] = Form.useForm();
  const [confirmLoading, setConfirmLoading] = React.useState(false);

  let formData = {
    name: "".age: "".address: "". props.userInfo }// Add props. Visible to trigger side effects based on certain dependencies
  useEffect(() = >{ formData = { ... formData, ... props.userInfo } form.setFieldsValue(formData); }, [props.visible]);// form.setFieldsValue(formData)

  / / sure
  const handleOk = () = > {
    // TODO:Form form
    props.onOk()
  }

  const handleOnSubmit = () = >{}/ / cancel
  const handleCancel = () = > {
    props.onCancel()
  }

  const onFinish = (values: any) = > {
    console.log(values);
    setConfirmLoading(true)
    setTimeout(() = > {
      props.onOk(values)
      setConfirmLoading(false)})}const onFinishFailed = () = > {
    // props.onFinish()
  }
  
/ / add forceRender
  return (
    <Modal
      forceRender
      title="Title"
      visible={props.visible}
      onOk={handleOk}
      confirmLoading={confirmLoading}
      onCancel={handleCancel}// Remove the bottomfooter={} []
    >
      <Form
        name="basic"
        form={form}
        labelCol={{ span: 8 }}
        wrapperCol={{ span: 16 }}
        initialValues={formData}
        onFinish={onFinish}
        onFinishFailed={onFinishFailed}
      >
        <Form.Item
          label="name"
          name="name"
          rules={[{ required: true.message: 'Please input your username!' }]}
        >
          <Input />
        </Form.Item>

        <Form.Item
          label="age"
          name="age"
          rules={[{ required: true.message: 'Please input your age!' }]}
        >
          <Input />
        </Form.Item>

        <Form.Item
          label="address"
          name="address"
          rules={[{ required: true.message: 'Please input your age!' }]}
        >
          <Input />
        </Form.Item>

        <Form.Item name="remember" valuePropName="checked" wrapperCol={{ offset: 8.span: 16}} >
          <Checkbox>Remember me</Checkbox>
        </Form.Item>

        <Form.Item wrapperCol={{ offset: 8.span: 16}} >
          <Button type="primary" htmlType="submit">
            Submit
          </Button>
        </Form.Item>
      </Form>
    </Modal>)}export default UserModel;
Copy the code

The last

If you have any questions or a better way, please leave a comment,

Added: 12 July 2021

When I looked at the Demo in the Ant Design documentation, I found an official demo that had nested forms in Modal

Official document address, posted here code:

// reset form fields when modal is form, closed
const useResetFormOnCloseModal = ({ form, visible }) = > {
  const prevVisibleRef = useRef();
  useEffect(() = > {
    prevVisibleRef.current = visible;
  }, [visible]);
  const prevVisible = prevVisibleRef.current;
  useEffect(() = > {
    if(! visible && prevVisible) { form.resetFields(); } }, [visible]); };const ModalForm = ({ visible, onCancel }) = > {
  const [form] = Form.useForm();
  useResetFormOnCloseModal({
    form,
    visible,
  });

  const onOk = () = > {
    form.submit();
  };

  return (
    <Modal title="Basic Drawer" visible={visible} onOk={onOk} onCancel={onCancel}>
      <Form form={form} layout="vertical" name="userForm">
        <Form.Item
          name="name"
          label="User Name"
          rules={[
            {
              required: true,},]} >
          <Input />
        </Form.Item>
        <Form.Item
          name="age"
          label="User Age"
          rules={[
            {
              required: true,},]} >
          <InputNumber />
        </Form.Item>
      </Form>
    </Modal>
  );
};
Copy the code