Warning: Instance created by `useForm` is not connected to any Form element.警告

1,486 阅读2分钟

antd Modal里面使用Form 出现 Warning: Instance created by useForm is not connected to any Form element 警告的问题原因以及解决方案

现象

Modal里面使用Form页面加载出现警告: image.png

原始代码

import React, { FC, useState, useEffect } from 'react'
import { Modal, Form } from 'antd'
import axios from '@/api/config'
import { ModifyModalProps } from '../../interface'
import { URL } from '../../constant'

const formItemLayout = {
  labelCol: {
    span: 6,
  },
  wrapperCol: {
    span: 14,
  },
}

const ModifyModal: FC<ModifyModalProps> = ({ modifyModalData, setModifyModal }) => {
  const { visible, id } = modifyModalData
  const [form] = Form.useForm()
  const [loading, setLoading] = useState<boolean>(false)
 
  useEffect(() => {
    if (!orgId) {
      form.resetFields()
      return
    }
    setLoading(true)
    // 获取form的initialValues
    axios
      .get(URL, { params: { id } })
      .then((res: any) => {
        setLoading(false)
        if (res?.data) {
          form.setFieldsValue({
            ...res.data,
          })
        }
      })
      .catch(() => {
        setLoading(false)
      })
  }, [orgId])

  const handleSubmit = async () => {
    try {
      setLoading(true)
      const values = await form.validateFields()
      console.log(values)
      setLoading(false)
    } catch (e) {
      setLoading(false)
    }
  }

  return (
    <Modal
      visible={visible}
      title='标题'
      destroyOnClose
      onCancel={() => {
        setModifyModal({ visible: false })
      }}
      onOk={handleSubmit}
      confirmLoading={loading}
    >
      <Form 
         labelWrap 
         form={form} 
         {...formItemLayout} 
         colon={false} 
         name='pay-modify-form'
       >
        // some FormItem
        // ...
      </Form>
    </Modal>
  )
}

export default ModifyModal

问题原因

ant design在Modal中使用Form表单,并且通过Form.useForm(), 获取form对象将其挂载到指定的Form表单后出现Instance created by useForm is not connect to any Form element. Forget to pass form prop警告。

大部分人可能以为:这是由于ant design的Modal组件会在Form表单之前创建,因此当页面初始化时form对象会找不到可关联的Form表单,于是出现上述警告。

但其实不是,出现这个警告的根本原因是form组件还没有渲染,就调用了 form 的方法(给表单赋值、获取表单的值等等)。百度这个警告内容给出的一堆方法是给什么 Model 加什么属性(如下方法1),都没有真正说到导致这个问题的原因,可能所处具体情景不一样吧,希望各位看官对症下药!

解决方法

  1. 网上普遍的方法是将 Modal组件中添加上 getContainer={false}属性

image.png

我试了一下并不起作用,而且如果当前Dom节点是antd的table的话,加载td,tr的样式还会影响到Modal样式。所以次方法不建议使用。

  1. modal加载后 form挂载之后再调用from的方法 上述代码改造如下:
import React, { FC, useState, useEffect } from 'react'
import { Modal, Form } from 'antd'
import axios from '@/api/config'
import { ModifyModalProps } from '../../interface'
import { URL } from '../../constant'

const formItemLayout = {
  labelCol: {
    span: 6,
  },
  wrapperCol: {
    span: 14,
  },
}

const ModifyModal: FC<ModifyModalProps> = ({ modifyModalData, setModifyModal }) => {
  const { visible, id } = modifyModalData
  const [form] = Form.useForm()
  const [loading, setLoading] = useState<boolean>(false)
 
  useEffect(() => {
    /*----------------start-------------------
        等到真正去挂载form后再调用form的方法
    */ 
    if (!visible) {
        return
    }
    /*----------------end-----------------*/
    if (!orgId) {
      form.resetFields()
      return
    }
    setLoading(true)
    axios
      .get(URL, { params: { id } })
      .then((res: any) => {
        setLoading(false)
        if (res?.data) {
          form.setFieldsValue({
            ...res.data,
          })
        }
      })
      .catch(() => {
        setLoading(false)
      })
  }, [orgId, visible])

  const handleSubmit = async () => {
    try {
      setLoading(true)
      const values = await form.validateFields()
      console.log(values)
      setLoading(false)
    } catch (e) {
      setLoading(false)
    }
  }

  return (
    <Modal
      visible={visible}
      title='标题'
      destroyOnClose
      onCancel={() => {
        setModifyModal({ visible: false })
      }}
      onOk={handleSubmit}
      confirmLoading={loading}
    >
      <Form 
        labelWrap 
        form={form} 
        {...formItemLayout} 
        colon={false} 
        name='pay-modify-form'
       >
        // some FormItem
        // ...
      </Form>
    </Modal>
  )
}

export default ModifyModal

或者在调用Modal组件的时候等到需要挂载时再挂载,: {modifyModalData.visible&&<ModifyModal modifyModalData={modifyModalData} setModifyModal={setModifyModal}/>

这两种改造方案都能解决问题!