https://next.ant.design/components/form-cn/#components-form-demo-form-in-modal
就直接用useForm 就行了。我参考的是弹出层中的示例。
const CollectionCreateForm = ({ onCancel }) => {
const [form] = Form.useForm();
form.setFieldsValue({
categoryName: caseDetail.categoryName,
});
return (
maskClosable={false}
title="修改项目基本信息"
okText="确定"
cancelText="取消"
onCancel={onCancel}
onOk={() => {
form
.validateFields()
.then(values => {
form.resetFields();
onCreate(values);
})
.catch(info => {
window.console.log('Validate Failed:', info);
});
}}
>
我只想能正常的用这个useForm
index.js:1 Warning: Instance created by useForm
is not connect to any Form element. Forget to pass form
prop?
in CollectionCreateForm ....
const [form] = Form.useForm();
form.setFieldsValue({
categoryName: caseDetail.categoryName,
});
| Environment | Info |
|---|---|
| antd | 4.0.0-rc.5 |
| React | 16.8.6 |
| System | mac10.15.3 |
| Browser | chrome |
我是按照官网直接来的,但是到处都报这个错,无语了。
Hello @LamTech. Please provide a online reproduction by forking this link https://u.ant.design/codesandbox-repro or a minimal GitHub repository. Issues labeled by Need Reproduce
will be closed if no activities in 7 days.
你好 @LamTech, 我们需要你提供一个在线的重现实例以便于我们帮你排查问题。你可以通过点击 此处 创建一个 codesandbox 或者提供一个最小化的 GitHub 仓库。7 天内未跟进的 issue 将会被自动关闭。
关键在于,我这个方法用起来了,但是它一直报这个错误警告。
Same problem here, but coludn't reproduce it on codesandbox.
+1
在Modal上加上forceRender这个属性
可以给setFieldsValue 方法加一个延迟
调用form.resetFields(); 就有这个好像。 本地启动的 http://localhost:8001/components/form-cn/#components-form-demo-form-context 会报出。
+1
使用setFieldsValue就会出现这个警告,但是能顺利呈现,,
useForm的的实例我是传递下去的
Modal 中的 Form 默认不会渲染,可以参考 @se7en00 的回复 给 Modal 加上 forceRender
。或者在 Modal 显示且渲染完成后再调用 setFieldsValue
和 resetFields
。
在使用V4版本(form存在于函数组件中)时我也是这问题困扰了整整两天,差点崩溃了(报错但不影响使用)最后细读https://ant.design/和https://next.ant.design/发现函数组件和类中使用form一定要理解并区分函数组件中的
useEffect(() => {
return () => {
form.resetFields();
};
})
在return ()=>{....}中触发销毁的是整个函数组件(没测试此时form是否被销毁)
文档说明:destroyOnClose | 关闭时销毁 Modal 里的子元素,默认 false。forceRender | 强制渲染 Modal,默认false。
解决方法:Modal的forceRender=true,destroyOnClose=false,此时Modal销毁时(关闭),不会报错。内部代码执行时可以找到form,但会报输入控件id重复警告(比错误要优雅点)。
Same problem +1
if your code involved setFieldsValue
or other functions alike, call it after nodes rendered
useEffect(() => {
form.setFieldsValue({
id: 1
})
}, [])
or
componentDidMount() {
form.setFieldsValue({
id: 1
})
}
It solved my problem
感觉上面的都不能完全解决这个问题,能不能在form上加个属性,指示form是否有Fields,让开发人员自己 判断是否要执行后面的代码
Same happens here
No fixed yet?
上面提到的方法都试遍了,没用
Modal 中的 Form 默认不会渲染,可以参考 @se7en00 的回复 给 Modal 加上
forceRender
。或者在 Modal 显示且渲染完成后再调用setFieldsValue
和resetFields
。
我用的抽屉时Drawer 虽然有forcerender这个API 但是和Modal不同 抽屉的这个API不是强制渲染而是预渲染,然后还是同样报错,所以有解决办法吗?怎么判断渲染完成了?
I solved. In drawer, use getContainer={false} can resolved it. I think Modal is the same.
我在抽屉里用getContainer={false}就好了 Modal应该也可以 出现同样问题的可以试一下
可以使用useRef保存Form对象,在使用form前 先判断useRef是否存在便可;
same problem here. form is assigned but keep failing.
如果在effect中,直接调用form.setFieldsValue, 即使加上forceRenter,重新打开Modal,还是会有这个warning,暂时解决只能effect中的setTimeout(() => form.setFieldsValue, 0)
解决了 抽屉出现的这个问题 我用getContainer={false}就不报warning了 出现同样问题的可以试一下 希望在Form的文档可以写清楚一点
谢谢,用这个方法解决了相同问题👍
你这个方法可行,能讲讲原理吗?
My workaround, create a ref
by useState
when Form
was rendered, then check the ref
before use the form instance.
interface FormModalProps {
data?: RoleProps;
visible: boolean;
onCancel?: () => void;
onSubmit?: (values: Store) => void;
submitting: boolean;
}
const FormModal: React.FC<FormModalProps> = props => {
const [form] = Form.useForm();
const [formRef, setFormRef] = useState(); // <---- set the ref when Form Rendered
const { data, onSubmit, onCancel, visible, submitting } = props;
// reset Form when modal close
useEffect(() => {
if ( !props.visible && formRef) { // <---- check ref before use the form instance
form.resetFields();
}
}, [props.visible]);
// fill Form when modal open
useEffect(() => {
if (visible && formRef) { // <---- check ref before use the form instance
form.setFieldsValue({
...data,
});
}
}, [props.data]);
// handle form onFinish
const handleFormFinish = (values: Store) => {
if (onSubmit) {
onSubmit(values);
}
};
// handle modal ok
const handleOk = () => {
if (!form) return;
form.submit();
};
return (
<Modal
title="Modal"
confirmLoading={submitting}
onOk={handleOk}
onCancel={onCancel}
visible={visible}
width={640}
>
<Form ref={setFormRef} form={form} onFinish={handleFormFinish}>
<Form.Item name="title" label="Title" >
<Input />
</Form.Item>
</Form>
</Modal>
);
};
No more warning again!
is it hard to discuss in English?
@muhaimincs https://ant.design/components/form/#Why-is-there-a-form-warning-when-used-in-Modal
if you use setFieldsValue, maybe try following code to replace(my foolish idea)。
<Modal **destroyOnClose** >
<Form **initialValues={formValues}**>
</Form>
</Modal>
I got it working.
Initially I was calling the antd component as
<Form blabla >
I then added the form prop in Form component -
<Form form={form} blabla >
Here the {form} comes from const [form] = Form.useForm();
Doc(That I was following) -
https://ant.design/components/form/#components-form-demo-form-in-modal
Your case might be different.
https://codesandbox.io/s/form-in-modal-to-create-ant-design-demo-xvcyv
Same problem, any body can fix that???
参照上面 linxianxi , https://github.com/ant-design/ant-design/issues/21543#issuecomment-598515368
Modal 我这边可以
<Modal
destroyOnClose={false}
getContainer={false}
forceRender
>
Modal 我这边可以
<Modal destroyOnClose={false} getContainer={false} forceRender >
Thank you, i fixed this problem by adding forceRender props in Modal
const [form] = Form.useForm()
<Form form={form} >
....
</Form>```
this did the trick for me.
I got it working.
Initially I was calling the antd component as
<Form blabla >
I then added the form prop in Form component -
<Form form={form} blabla >
Here the {form} comes from
const [form] = Form.useForm();
Doc(That I was following) -
https://ant.design/components/form/#components-form-demo-form-in-modalYour case might be different.
This fixed it for me too. I was using the form in a drawer, not a modal
The secret combo for me was:
useEffect(() => {
if (form && visible) {
if (current) {
setTimeout (() => form.setFieldsValue({
...current,
}), 0);
} else {
form.resetFields();
}
}
}, [current]);
Same error here without modal and form prop pass to Form component
https://codesandbox.io/s/basic-usage-ant-design-demo-6llbw?file=/index.js:1618-1661
Same error here without modal and form prop pass to Form component
https://codesandbox.io/s/basic-usage-ant-design-demo-6llbw?file=/index.js:1618-1661
Fix for yours :https://codesandbox.io/s/basic-usage-ant-design-demo-ksuz8?file=/index.js
you should move the form.getVieldValue into a Form.Item component
<Form.Item
shouldUpdate={(prevValues, curValues) =>
prevValues.username !== curValues.username
}
noStyle
>
{() => <div>{form.getFieldValue("username")}</div>}
</Form.Item>
another method would be to use a useRef()
Draw + Form. For Modal + Form, the method applies.
const MyComp = React.memo(() => {
const [form] = Form.useForm();
const { getFieldValue } = form;
const category = getFieldValue('category'); // It's the culprit
return (/* something */);
})
Proper use: Form methods
<Form.Item
noStyle
shouldUpdate={(prevValues, currentValues) => prevValues.gender !== currentValues.gender}
>
{({ getFieldValue }) => {
return getFieldValue('gender') === 'other' ? (
<Form.Item name="customizeGender" label="Customize Gender" rules={[{ required: true }]}>
<Input />
</Form.Item>
) : null;
}}
</Form.Item>
const MyComp = React.memo(() => {
const [form] = Form.useForm();
const { getFieldValue } = form;
const category = getFieldValue('category'); // It's the culprit
return (/* something */);
})
正确的使用方式: 表单方法调用
<Form.Item
noStyle
shouldUpdate={(prevValues, currentValues) => prevValues.gender !== currentValues.gender}
>
{({ getFieldValue }) => {
return getFieldValue('gender') === 'other' ? (
<Form.Item name="customizeGender" label="Customize Gender" rules={[{ required: true }]}>
<Input />
</Form.Item>
) : null;
}}
</Form.Item>
It happen because form element have not been rendered, but You have set values for form. I think this is basic knowledge about react and hooks.. You can use setTimeout for waiting rendered form.
But best way to set initial value of form is
<Form
initialValues={{
name: 'Hafid',
age: '35'
}}
onFinish={onFinish}
>
or with this method
```js
const [values, setValues] = React.useState({})
React.useEffect(()=>{
// get data values from web service or API
// fecth(...)
if (values_from_api){
setValues(values_from_api);
}
}, [])
return <>
What if I need to use form values in my own custom hook?
With Ant 3 I did it like that:
const [updating, updateInfo] = useMyOwnCustomHookForSubmitAction(getFieldsValue());
const submitForm = () => {
validateFields((err) => {
if (!err) updateInfo();
});
};
<Form>...</Form>
With Ant 4 if I try to do it like that, I will get this error from the topic.
const [form] = useForm();
const [updating, updateInfo] = useMyOwnCustomHookForSubmitAction(getFieldsValue());
const submitForm = () => {
validateFields((err) => {
if (!err) updateInfo();
});
};
<Form form={form}>...</Form>
Form is in Modal, forceRender=true, destroyOnClose=false set. What am I doing wrong?
在使用V4版本(form存在于函数组件中)时我也是这问题困扰了整整两天,差点崩溃了(报错但不影响使用)最后细读https://ant.design/和https://next.ant.design/发现函数组件和类中使用form一定要理解并区分函数组件中的
useEffect(() => {
return () => {
form.resetFields();
};
})
在return ()=>{....}中触发销毁的是整个函数组件(没测试此时form是否被销毁)
文档说明:destroyOnClose | 关闭时销毁 Modal 里的子元素,默认 false。forceRender | 强制渲染 Modal,默认false。
解决方法:Modal的forceRender=true,destroyOnClose=false,此时Modal销毁时(关闭),不会报错。内部代码执行时可以找到form,但会报输入控件id重复警告(比错误要优雅点)。
我也遇到这个问题,我是这样方法解决的
Modal配置forceRender | 强制渲染
Modla 表单里面 name={['modal', 'cityCode']}
筛选 表单里面 name={['search', 'cityCode']} or name='cityCode'
这样就可以 解决所有的warning 了 也不会报那个 Found 2 elements with non-unique id 警告了⚠
可以用useRef来引用form的ref, 用 formRef.current 里面的方法
const formRef = useRef()
return (<Form ref={formRef}>
{
(formRef.current && formRef.current.getFieldsValue('key') === 1)
&&
(<Input />)
}
</Form>)
Modal 中的 Form 默认不会渲染,可以参考 @se7en00 的回复 给 Modal 加上
forceRender
。或者在 Modal 显示且渲染完成后再调用setFieldsValue
和resetFields
。
在Modal上加上forceRender这个属性 根本没有用
官方的区块中的示例也警告的
在使用V4版本(form存在于函数组件中)时我也是这问题困扰了整整两天,差点崩溃了(报错但不影响使用)最后细读https://ant.design/和https://next.ant.design/发现函数组件和类中使用form一定要理解并区分函数组件中的
useEffect(() => {
return () => {
form.resetFields();
};
})
在return ()=>{....}中触发销毁的是整个函数组件(没测试此时form是否被销毁)
文档说明:destroyOnClose | 关闭时销毁 Modal 里的子元素,默认 false。forceRender | 强制渲染 Modal,默认false。
解决方法:Modal的forceRender=true,destroyOnClose=false,此时Modal销毁时(关闭),不会报错。内部代码执行时可以找到form,但会报输入控件id重复警告(比错误要优雅点)。
这个方法可以解决,但是如果在Modal外层先用三元运算符visible ? 判断下且把forceRender=true,destroyOnClose=false这样:
{visible ? : <Modal visible={visible} forceRender destroyOnClose={false}><Form form={form} onFinish={handleFinish}>...</Form></Modal> : null}
就出问题: 只显示mask 不显示弹框
这样设置forceRender=true,destroyOnClose=false,在弹框onOk或者onCancel关闭时候再使用form.resetFields()就不会再报错了
<Modal
visible={visible}
forceRender
destroyOnClose={false}
>
<Form form={form} onFinish={handleFinish}>...</Form>
</Modal>
但是如果在Modal外层先用三元运算符visible ? 判断下且把forceRender=true,destroyOnClose=false这样:
{visible
? <Modal
visible={visible}
forceRender
destroyOnClose={false}
>
<Form form={form} onFinish={handleFinish}>...</Form>
</Modal>
: null
}
就出问题: 只显示mask 不显示弹框
官方给出的解决方法
链接
在使用V4版本(form存在于函数组件中)时我也是这问题困扰了整整两天,差点崩溃了(报错但不影响使用)最后细读https://ant.design/和https://next.ant.design/发现函数组件和类中使用form一定要理解并区分函数组件中的
useEffect(() => {
return () => {
form.resetFields();
};
})
在return ()=>{....}中触发销毁的是整个函数组件(没测试此时form是否被销毁)
文档说明:destroyOnClose | 关闭时销毁 Modal 里的子元素,默认 false。forceRender | 强制渲染 Modal,默认false。
解决方法:Modal的forceRender=true,destroyOnClose=false,此时Modal销毁时(关闭),不会报错。内部代码执行时可以找到form,但会报输入控件id重复警告(比错误要优雅点)。我也遇到这个问题,我是这样方法解决的
Modal配置forceRender | 强制渲染
Modla 表单里面 name={['modal', 'cityCode']}
筛选 表单里面 name={['search', 'cityCode']} or name='cityCode'
这样就可以 解决所有的warning 了 也不会报那个 Found 2 elements with non-unique id 警告了⚠
【表单名称,会作为表单字段 id 前缀使用】所以没有 Found 2 elements with non-unique id 警告了
getContainer={false} as modal property + having the modal visible when I call form.resetFields() works for me to not show the warning
useEffect(() => {
if (form && visible) {
form.resetFields();
}
}, [visible]);
In this way, destroyOnClose can be also true
I use useRef instead of Form.useFrom to get Form instance, it works for me
const [visible, setVisible] = useState(false)
let form = useRef(null)
const closeModal = () => {
setVisible(false)
form.resetFields()
}
return (
<Modal
title="test"
visible={visible}
onCancel={closeModal}
footer={null}
>
<Form
name="test"
layout="vertical"
onFinish={onFinish}
ref={instance => { form = instance }}
>
<Form.Item
label="item"
name="item"
>
<Input />
</Form.Item>
<Form.Item
style={{
textAlign: 'right',
}}
>
<Space size="middle">
<Button type="primary" htmlType="submit">
submit
</Button>
<Button onClick={closeModal}>
cancle
</Button>
</Space>
</Form.Item>
</Form>
</Modal>
)
Just my two cents: this error appeared for me when I tried to reset a form that was not mounted, so adding a dependency to a required constant solved it.
useEffect(() => {
if (data) { // data is used to populate initialValues
form.resetFields();
}
}, [form, data])
EDIT: pretty much what @fabripeco said :D
I use form in Popover, useRef
is usable for me, I think it's usable for modal
const formRef = useRef(null);
<Popover
content={renderEdit()}
visible={isEdit}
onVisibleChange={onToggleEdit}
>
<span onClick={onToggleEdit}>
{name}
</span>
</Popover>
function renderEdit() {
return (
<Form
initialValues={{ newName: name }}
form={form}
ref={formRef}
>
</Form>
);
}
function onToggleEdit() {
if (isEdit) {
toggleEdit(false);
} else if (!isEdit) {
if (formRef.current) {
form.setFieldsValue({
newName: name
});
}
toggleEdit(true);
}
}
My workaround, create a
ref
byuseState
whenForm
was rendered, then check theref
before use the form instance.interface FormModalProps { data?: RoleProps; visible: boolean; onCancel?: () => void; onSubmit?: (values: Store) => void; submitting: boolean; } const FormModal: React.FC<FormModalProps> = props => { const [form] = Form.useForm(); const [formRef, setFormRef] = useState(); // <---- set the ref when Form Rendered const { data, onSubmit, onCancel, visible, submitting } = props; // reset Form when modal close useEffect(() => { if ( !props.visible && formRef) { // <---- check ref before use the form instance form.resetFields(); } }, [props.visible]); // fill Form when modal open useEffect(() => { if (visible && formRef) { // <---- check ref before use the form instance form.setFieldsValue({ ...data, }); } }, [props.data]); // handle form onFinish const handleFormFinish = (values: Store) => { if (onSubmit) { onSubmit(values); } }; // handle modal ok const handleOk = () => { if (!form) return; form.submit(); }; return ( <Modal title="Modal" confirmLoading={submitting} onOk={handleOk} onCancel={onCancel} visible={visible} width={640} > <Form ref={setFormRef} form={form} onFinish={handleFormFinish}> <Form.Item name="title" label="Title" > <Input /> </Form.Item> </Form> </Modal> ); };
No more warning again!
solved perfectly!
Two reason case this Warning:
1.
I solve use this:
<Modal
getContainer={false}
// destroyOnClose
>
官方给出的解决方法
链接
完美,再给modal添加forceRender
为什么不把formHooked
暴露出来让用户自己判断一下,上面那些绕来绕去的方法不觉得累吗。
Most helpful comment
I solved. In drawer, use getContainer={false} can resolved it. I think Modal is the same.
我在抽屉里用getContainer={false}就好了 Modal应该也可以 出现同样问题的可以试一下