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 将会被自动关闭。
关键在于,我这个方法用起来了,但是它一直报这个错误警告。
这里有同样的问题,但不能在 codeandbox 上重现它。
+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重复警告(比错误要优雅点)。
同样的问题+1
如果您的代码涉及setFieldsValue
或其他类似函数,请在节点呈现后调用它
useEffect(() => {
form.setFieldsValue({
id: 1
})
}, [])
或者
componentDidMount() {
form.setFieldsValue({
id: 1
})
}
它解决了我的问题
感觉上面的都不能完全解决这个问题,能不能在form上加个属性,指示form是否有Fields,让开发人员自己 判断是否要执行后面的代码
同样发生在这里
还没修好?
上面提到的方法都试遍了,没用
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是否存在便可;
同样的问题在这里。 表单已分配但一直失败。
如果在effect中,直接调用form.setFieldsValue, 即使加上forceRenter,重新打开Modal,还是会有这个warning,暂时解决只能effect中的setTimeout(() => form.setFieldsValue, 0)
解决了 抽屉出现的这个问题 我用getContainer={false}就不报warning了 出现同样问题的可以试一下 希望在Form的文档可以写清楚一点
谢谢,用这个方法解决了相同问题👍
你这个方法可行,能讲讲原理吗?
我的解决方法是,在呈现Form
时通过useState
创建一个ref
,然后在使用表单实例之前检查ref
。
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>
);
};
不再警告!
用英语讨论很难吗?
如果你使用 setFieldsValue,不妨试试下面的代码来替换(我的愚蠢想法)。
<Modal **destroyOnClose** >
<Form **initialValues={formValues}**>
</Form>
</Modal>
我让它工作了。
最初我将 antd 组件称为<Form blabla >
然后我在 Form 组件中添加了 form prop -
<Form form={form} blabla >
这里的 {form} 来自const [form] = Form.useForm();
Doc(我一直在关注)-
https://ant.design/components/form/#components -form-demo-form-in-modal
您的情况可能有所不同。
https://codesandbox.io/s/form-in-modal-to-create-ant-design-demo-xvcyv
同样的问题,任何机构都可以解决这个问题???
参照上面 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.
我让它工作了。
最初我将 antd 组件称为<Form blabla >
然后我在 Form 组件中添加了 form prop -
<Form form={form} blabla >
这里的 {form} 来自
const [form] = Form.useForm();
Doc(我一直在关注)-
https://ant.design/components/form/#components -form-demo-form-in-modal您的情况可能有所不同。
这也为我修好了。 我在抽屉里使用表格,而不是模态
我的秘密组合是:
useEffect(() => {
如果(形式&&可见){
如果(当前){
setTimeout (() => form.setFieldsValue({
...当前的,
}), 0);
} 别的 {
form.resetFields();
}
}
}, [当前的]);
在没有模态和表单道具传递给表单组件的情况下,这里出现相同的错误
https://codesandbox.io/s/basic-usage-ant-design-demo-6llbw?file=/index.js :1618-1661
在没有模态和表单道具传递给表单组件的情况下,这里出现相同的错误
https://codesandbox.io/s/basic-usage-ant-design-demo-6llbw?file=/index.js :1618-1661
修复你的: https : =/index.js
您应该将 form.getVieldValue 移动到 Form.Item 组件中
<Form.Item
shouldUpdate={(prevValues, curValues) =>
prevValues.username !== curValues.username
}
noStyle
>
{() => <div>{form.getFieldValue("username")}</div>}
</Form.Item>
另一种方法是使用 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>
发生这种情况是因为尚未呈现表单元素,但您已为表单设置了值。 我认为这是关于 react 和 hooks 的基本知识。你可以使用 setTimeout 来等待渲染表单。
但是设置表单初始值的最佳方法是
<Form
initialValues={{
name: 'Hafid',
age: '35'
}}
onFinish={onFinish}
>
或者用这个方法
```js
const [values, setValues] = React.useState({})
React.useEffect(()=>{
// 从 Web 服务或 API 获取数据值
// feth(...)
如果(values_from_api){
setValues(values_from_api);
}
}, [])
返回<>
如果我需要在我自己的自定义钩子中使用表单值怎么办?
使用 Ant 3 我是这样做的:
const [updating, updateInfo] = useMyOwnCustomHookForSubmitAction(getFieldsValue());
const submitForm = () => {
validateFields((err) => {
if (!err) updateInfo();
});
};
<Form>...</Form>
使用 Ant 4,如果我尝试这样做,我会从主题中得到这个错误。
const [form] = useForm();
const [updating, updateInfo] = useMyOwnCustomHookForSubmitAction(getFieldsValue());
const submitForm = () => {
validateFields((err) => {
if (!err) updateInfo();
});
};
<Form form={form}>...</Form>
表单在 Modal 中,forceRender=true,destroyOnClose=false 设置。 我究竟做错了什么?
在使用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} 作为模态属性 + 当我调用 form.resetFields() 时具有可见的模态对我来说不显示警告
useEffect(() => {
if (form && visible) {
form.resetFields();
}
}, [visible]);
这样,destroyOnClose 也可以为真
我使用 useRef 而不是 Form.useFrom 来获取 Form 实例,它对我有用
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>
)
只是我的两分钱:当我尝试重置未安装的表单时出现此错误,因此向所需常量添加依赖项解决了它。
useEffect(() => {
if (data) { // data is used to populate initialValues
form.resetFields();
}
}, [form, data])
编辑:几乎@fabripeco所说的:D
我在 Popover 中使用表单, useRef
对我可用,我认为它可用于模态
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);
}
}
我的解决方法是,在呈现
Form
时通过useState
创建一个ref
,然后在使用表单实例之前检查ref
。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> ); };
不再警告!
完美解决!
两个原因案例此警告:
1.
我解决使用这个:
<Modal
getContainer={false}
// destroyOnClose
>
官方给出的解决方法
链接
完美,再给modal添加forceRender
为什么不把formHooked
暴露出来让用户自己判断一下,上面那些绕来绕去的方法不觉得累吗。
最有用的评论
I solved. In drawer, use getContainer={false} can resolved it. I think Modal is the same.
我在抽屉里用getContainer={false}就好了 Modal应该也可以 出现同样问题的可以试一下