如何获取存于变量/Props中的Ant Design Form表单元素值?
问题:动态生成的Form.Item无法被Ant Design Form捕获值
我通过模板替换生成包含<Form.Item>和<Input>的HTML字符串,再用html-react-parser解析成React元素(赋值给body变量)嵌入Form组件。提交表单时获取到的是空对象,但直接编写<Form.Item>搭配<Input>就能正常取值。
模板内容
<p><strong>Commercial start of +++SERVICE+++</strong> <strong>roaming service</strong></p><p><strong>between,</strong></p><p><strong>+++OPERATOR_A+++, +++COUNTRY_A+++ (+++TADIG_A+++)</strong></p><p>&</p><p><strong>+++OPERATOR_B+++, +++COUNTRY_B+++ (+++TADIG_B+++)</strong></p><p>This is to confirm that on <strong>+++LAUNCH_DATE+++</strong></p><p>Agree to launch +++SERVICE+++ service on a bilateral basis. The launch follows the successful completion of the applicable IREG and TADIG tests.</p><table><tr><td><p><strong>For +++OPERATOR_A+++</strong></p><p><strong>Date: +++SIGNATURE_DATE+++</strong></p><p><strong>+++RESPONSIBLE_A_NAME+++</strong></p><p><strong>Title: +++RESPONSIBLE_A_DESIGNATION+++</strong></p><p><strong>+++IMAGE signature()+++</strong></p></td><td><p><strong>For +++OPERATOR_B+++</strong></p><p><strong> Date: </strong></p><p><strong>+++RESPONSIBLE_B_NAME+++</strong></p><p><strong>Title: +++RESPONSIBLE_B_DESIGNATION+++</strong></p></td></tr></table>
原代码
import { LoadingOutlined, PlusOutlined } from '@ant-design/icons'; import {message, Form, Button , Input} from 'antd'; import React, { useState } from 'react'; import './HtmlContract.css'; import parse from 'html-react-parser'; const layout = { labelCol: { span: 8, }, wrapperCol: { span: 16, }, } function HtmlContract(props) { const [html, setHtml] = useState(props.templateContract.value); const replaceInputsAndImages = () => { if (html.includes('+++')) { let mySubString = html.substring( html.indexOf("+++") + 3, html.indexOf("+++", html.indexOf("+++") + 3) ); setHtml(html.replaceAll("+++" + mySubString + "+++",`<Form.Item label='${mySubString}' name='${mySubString}'><Input placeholder='${mySubString}' /></Form.Item> `)); }}; const [loading, setLoading] = useState(false); const [form] = Form.useForm() React.useEffect(() => { replaceInputsAndImages(); }); const onFinish = async (values) => { console.log(values) } const body = parse(html); return (<> <Form onFinish={onFinish} onFinishFailed={(errorInfo) => console.log(errorInfo)} form={form} {...layout} name='contract-form'> {body} <Form.Item wrapperCol={{ ...layout.wrapperCol, offset: 8 }}> <Button type='primary' htmlType='submit' style={{ float: 'right' }}> Save </Button> </Form.Item> </Form> </> ); } export default HtmlContract;
核心原因
- 上下文关联失效:Ant Design Form通过React上下文(Context)管理字段状态,
html-react-parser解析生成的<Form.Item>是孤立的React元素,没有接入外层Form的上下文,导致Form无法识别这些动态字段。 - 替换逻辑缺陷:原代码的
replaceInputsAndImages每次仅替换一个变量,且useEffect无依赖项,会触发无限循环渲染,进一步加剧状态混乱。
解决方案
方案1:直接生成React元素(推荐)
跳过HTML字符串解析步骤,直接从模板提取变量并生成<Form.Item>组件,确保字段与Form上下文正常关联:
import { Form, Button, Input } from 'antd'; import React, { useState, useEffect } from 'react'; import './HtmlContract.css'; const layout = { labelCol: { span: 8 }, wrapperCol: { span: 16 }, } // 提取模板中的所有变量 const extractVariables = (html) => { const regex = /\+\+\+([^+]+)\+\+\+/g; const uniqueVars = new Set(); let match; while ((match = regex.exec(html)) !== null) { // 过滤图片类型变量 if (!match[1].startsWith('IMAGE')) { uniqueVars.add(match[1]); } } return Array.from(uniqueVars); } function HtmlContract(props) { const [templateHtml] = useState(props.templateContract.value); const [formFields, setFormFields] = useState([]); const [form] = Form.useForm() useEffect(() => { const variables = extractVariables(templateHtml); // 动态生成Form.Item组件数组 const fields = variables.map(name => ( <Form.Item key={name} label={name} name={name}> <Input placeholder={name} /> </Form.Item> )); setFormFields(fields); }, [templateHtml]); const onFinish = (values) => { console.log(values) } return ( <Form onFinish={onFinish} onFinishFailed={(errorInfo) => console.log(errorInfo)} form={form} {...layout} name='contract-form'> {formFields} <Form.Item wrapperCol={{ ...layout.wrapperCol, offset: 8 }}> <Button type='primary' htmlType='submit' style={{ float: 'right' }}> Save </Button> </Form.Item> </Form> ); } export default HtmlContract;
方案2:保留原HTML结构的混合渲染
如果需要保留模板中的段落、表格等结构,可拆分模板文本与变量,插入对应的Form字段:
import { Form, Button, Input } from 'antd'; import React, { useState, useEffect } from 'react'; import './HtmlContract.css'; import parse from 'html-react-parser'; const layout = { labelCol: { span: 8 }, wrapperCol: { span: 16 }, } const extractVariables = (html) => { const regex = /\+\+\+([^+]+)\+\+\+/g; const uniqueVars = new Set(); let match; while ((match = regex.exec(html)) !== null) { if (!match[1].startsWith('IMAGE')) { uniqueVars.add(match[1]); } } return Array.from(uniqueVars); } // 解析模板,替换变量为对应Form字段 const parseTemplate = (html, fieldsMap) => { const regex = /\+\+\+([^+]+)\+\+\+/g; const parts = html.split(regex); return parts.map((part, index) => { if (fieldsMap[part]) { return fieldsMap[part]; } // 解析普通HTML文本 return parse(part); }); } function HtmlContract(props) { const [templateHtml] = useState(props.templateContract.value); const [content, setContent] = useState([]); const [form] = Form.useForm() useEffect(() => { const variables = extractVariables(templateHtml); const fieldsMap = {}; variables.forEach(name => { fieldsMap[name] = ( <Form.Item key={name} label={name} name={name}> <Input placeholder={name} /> </Form.Item> ); }); // 生成包含原HTML结构和Form字段的内容 const parsedContent = parseTemplate(templateHtml, fieldsMap); setContent(parsedContent); }, [templateHtml]); const onFinish = (values) => { console.log(values) } return ( <Form onFinish={onFinish} onFinishFailed={(errorInfo) => console.log(errorInfo)} form={form} {...layout} name='contract-form'> {content} <Form.Item wrapperCol={{ ...layout.wrapperCol, offset: 8 }}> <Button type='primary' htmlType='submit' style={{ float: 'right' }}> Save </Button> </Form.Item> </Form> ); } export default HtmlContract;
方案3:修复原代码的循环问题(仅辅助,无法解决核心取值问题)
若暂时保留原HTML解析方式,需先修复无限循环:
React.useEffect(() => { replaceInputsAndImages(); }, [html]); // 添加html作为依赖,避免无限循环
内容的提问来源于stack exchange,提问作者kais
相关产品推荐
相关产品推荐

