React Final Form:表单外按钮提交数据及handleSubmit报错解决
解决"cannot find name 'handleSubmit'"错误及表单提交流程
1. 完善父组件(InvoiceList.tsx)逻辑
首先在父组件中定义提交处理函数,传递给子表单组件,并让外部按钮触发表单提交:
import { useRef } from 'react'; import InvoiceForm from './InvoiceForm'; import Button from './Button'; const InvoiceList = () => { // 保存表单引用,用于外部触发提交 const invoiceFormRef = useRef<any>(null); // 定义提交逻辑:将表单数据推送到数据库 const handleSubmit = async (formValues: any) => { try { // 替换为你的数据库请求逻辑,比如调用后端API await fetch('/api/invoices', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(formValues) }); console.log('表单提交成功'); // 可添加提交成功后的操作:重置表单、提示用户等 } catch (error) { console.error('提交失败:', error); } }; // 触发表单提交的方法 const triggerFormSubmit = () => { invoiceFormRef.current?.submitForm(); }; return ( <div> {/* 给子表单传递提交函数和ref */} <InvoiceForm handleSubmit={handleSubmit} invoice={/* 传入你的Cart类型数据 */} ref={invoiceFormRef} /> {/* 外部Create按钮 */} <Button onClick={triggerFormSubmit}> Create </Button> </div> ); }; export default InvoiceList;
2. 修正子表单组件(InvoiceForm.tsx)
通过forwardRef暴露提交方法,修正命名冲突并确保表单实例正确调用:
import { forwardRef, useImperativeHandle, useLazyRef } from 'react'; import { Form, Field, FieldArray, createForm, arrayMutators } from 'react-final-form'; const initialValues = { name: '', description: '' }; // 使用forwardRef让父组件获取表单引用 const InvoiceForm = forwardRef(({ handleSubmit: onFormSubmit, invoice, }: { handleSubmit: (values: any) => void invoice: Cart }, ref) => { const form = useLazyRef(() => createForm({ initialValues: { invoices: invoice != null ? invoice.items.map((item) => ({ name: item.name, description: item.description })) : [initialValues] }, keepDirtyOnReinitialize: false, mutators: { ...arrayMutators }, onSubmit: onFormSubmit })); // 向父组件暴露提交方法 useImperativeHandle(ref, () => ({ submitForm: () => { form.current.submit(); } })); return ( <div className="c-invoices-content"> <div className="c-invoices-panel"> <div className="c-invoices-panel__body"> <Form form={form.current} render={({ handleSubmit, values }) => { return ( <form id="invoice-form" autoComplete="off" onSubmit={handleSubmit} className="form" > <FieldArray name="invoices"> {({ fields }) => fields.map((name, index) => { const isFirst = index === 0; return ( <div className="form-field-row" key={name}> <Field className="textfield" name={`${name}.name`} component={TextInput} placeholder="Name" formInline formLabel={isFirst ? 'Item Name' : ''} validate={(value) => value ? undefined : 'Name can\'t be blank'} /> <Field className="textfield" name={`${name}.description`} component={TextInput} placeholder="Description" formInline formLabel={isFirst ? 'Description' : ''} validate={(value) => value ? undefined : 'Description can\'t be blank'} /> <Button className="form-field__action" onClick={() => fields.remove(index)} > <Trash color="#555" size={24} /> </Button> </div> ); })} </FieldArray> <div className="form-field-row"> <Button type="secondary" onClick={() => form.current.mutators.push('invoices', initialValues)} className="--border-dashed" > + Add Item </Button> </div> </form> ); }} /> </div> </div> </div> ); }); export default InvoiceForm;
关键修正点
- 补全缺失的props传递:原错误核心是父组件未向
InvoiceForm传入handleSubmit函数,现在在父组件中定义并传递该函数。 - 实现外部触发提交:通过
forwardRef和useImperativeHandle让父组件能调用表单内部的提交方法,实现外部按钮触发提交。 - 避免命名冲突:将props中的
handleSubmit重命名为onFormSubmit,与Form组件render回调中的handleSubmit区分开,消除混淆。 - 修正表单实例调用:确保
form.current正确访问表单实例,调用mutators和submit方法。
内容的提问来源于stack exchange,提问作者Ced
相关产品推荐
相关产品推荐

