AntD Modal内嵌Steps无法获取第二步Form数据问题
AntD Modal内Steps嵌入多Form无法获取第二步Form数据的解决方案
问题现象
在AntD Modal组件的Steps中嵌入两个独立Form,每个Form都创建了独立的useForm实例并单独校验,但无法获取第二步Form的数据。将该Form移至第一步时可正常获取数据,推测是Steps加载时的hydration(水合)问题。原代码如下:
import { React, FC } from "react"; const Form = () => { const [Form1] = useForm(); const [Form2] = useForm(); const checkFormValidations = async () => { try { const data = await realtorForm1.validateFields(); next(); } catch (e) { message.error(e.message.data); } }; const checkForm2Validations = async () => { try { const data = await realtorForm2.validateFields(); // I am not getting this data // Calling API to Add Data } catch (e) { message.error(e.message.data); } }; const steps = [ { key: 1, title: "First", content: ( <Form form={Form1} initialValues={DataProps} validateTrigger="onBlur" ></Form> ), }, { key: 2, title: "Second", content: ( <Form form={Form2} initialValues={DataProps} validateTrigger="onBlur" ></Form> ), }, ]; return ( <Modal> <Steps current={current} items={items} /> <div style={contentStyle}>{steps[current].content}</div> <div style={{ display: "flex" }}> {current < steps.length - 1 && ( <BaseButton type="primary" onClick={() => checkFormValidations()}> Next </BaseButton> )} {current > 0 && ( <BaseButton style={{ margin: "0 8px" }} onClick={() => prev()}> Previous </BaseButton> )} {current === steps.length - 1 && ( <BaseButton type="primary" onClick={() => checkForm2Validations()}> Submit </BaseButton> )} </div> </Modal> ); };
问题原因
- 变量名不一致:校验方法中使用
realtorForm1/realtorForm2,但实际定义的实例是Form1/Form2,直接导致调用失败。 - 组件命名冲突:自定义组件名为
Form,与AntD的Form组件重名,React无法正确识别AntD Form。 - 预渲染导致实例失效:两个Form提前写在
steps数组中初始化时会被预渲染,非当前步骤的Form会被卸载,导致useForm实例与DOM元素解绑,切换到第二步时实例无法同步更新。
解决方案
1. 修正命名问题
- 将自定义组件名改为
MultiStepForm,避免与AntD Form重名; - 统一
useForm实例的变量名,确保校验时调用正确实例。
2. 动态渲染Form
通过条件渲染确保只有当前步骤的Form被挂载,避免预渲染导致的实例失效。
修正后的完整代码
import React, { useState } from "react"; import { Modal, Steps, Form as AntdForm, Button, message } from "antd"; const MultiStepForm = () => { const [currentStep, setCurrentStep] = useState(0); const [form1] = AntdForm.useForm(); const [form2] = AntdForm.useForm(); const nextStep = () => { setCurrentStep(prev => prev + 1); }; const prevStep = () => { setCurrentStep(prev => prev - 1); }; const checkForm1Validations = async () => { try { const data = await form1.validateFields(); console.log("第一步数据:", data); nextStep(); } catch (e) { message.error(e.message || "表单校验失败"); } }; const checkForm2Validations = async () => { try { const data = await form2.validateFields(); console.log("第二步数据:", data); // 调用API提交数据 message.success("提交成功"); } catch (e) { message.error(e.message || "表单校验失败"); } }; const steps = [ { key: "1", title: "第一步" }, { key: "2", title: "第二步" }, ]; const contentStyle = { padding: "24px 0" }; return ( <Modal title="多步骤表单" open={true} footer={null}> <Steps current={currentStep} items={steps} /> <div style={contentStyle}> {currentStep === 0 && ( <AntdForm form={form1} initialValues={{ name: "", email: "" }} validateTrigger="onBlur" > <AntdForm.Item name="name" label="姓名" rules={[{ required: true, message: "请输入姓名" }]} > <input placeholder="请输入姓名" /> </AntdForm.Item> <AntdForm.Item name="email" label="邮箱" rules={[{ required: true, type: "email", message: "请输入正确的邮箱" }]} > <input placeholder="请输入邮箱" /> </AntdForm.Item> </AntdForm> )} {currentStep === 1 && ( <AntdForm form={form2} initialValues={{ phone: "", address: "" }} validateTrigger="onBlur" > <AntdForm.Item name="phone" label="手机号" rules={[{ required: true, message: "请输入手机号" }]} > <input placeholder="请输入手机号" /> </AntdForm.Item> <AntdForm.Item name="address" label="地址" rules={[{ required: true, message: "请输入地址" }]} > <input placeholder="请输入地址" /> </AntdForm.Item> </AntdForm> )} </div> <div style={{ display: "flex" }}> {currentStep < steps.length - 1 && ( <Button type="primary" onClick={checkForm1Validations}> 下一步 </Button> )} {currentStep > 0 && ( <Button style={{ margin: "0 8px" }} onClick={prevStep}> 上一步 </Button> )} {currentStep === steps.length - 1 && ( <Button type="primary" onClick={checkForm2Validations}> 提交 </Button> )} </div> </Modal> ); }; export default MultiStepForm;
关键优化点
- 通过
currentStep条件渲染,仅挂载当前步骤的Form,避免实例与DOM解绑; - 修正了变量名冲突和调用错误;
- 完善了步骤切换的状态管理逻辑。
内容的提问来源于stack exchange,提问作者Rahul Rajan
相关产品推荐
相关产品推荐

