React Final Form:仅合法字段提交及onSubmit差异问询
Hey there! Let's tackle your two react-final-form issues one by one and get that contact form working properly.
1. How to Prevent Submission Until All Fields Are Valid
Right now, your form is ignoring react-final-form's validation checks because you're using a custom handleSubmit tied directly to the native <form> tag. Here's how to fix this:
- Use react-final-form's built-in
handleSubmit: Therenderprop gives you a pre-wrappedhandleSubmitfunction that runs validation first. Pass this to the native<form>'sonSubmitinstead of your custom method. - Move your API logic to the Form component's
onSubmit: This callback will only execute if yourvalidatefunction returns an emptyerrorsobject (meaning all fields are valid). - Stop using refs: You don't need to manually grab input values—react-final-form collects all field data into the
valuesobject that gets passed to theonSubmitfunction.
2. What's the Difference Between <Form/>'s onSubmit and Native <form>'s onSubmit?
Let's clarify these two to avoid confusion:
<Form/>component'sonSubmit: This is react-final-form's submission handler. It waits for validation to pass first, then sends the validatedvaluesto your function. This is where you should put your fetch request, alert, or any other submission logic.- Native
<form>'sonSubmit: This is the browser's default submit event. If you bind your own function here (like you did withthis.handleSubmit), it runs immediately when the submit button is clicked—bypassing react-final-form's validation entirely. The correct approach is to pass thehandleSubmitfrom the render prop to this event, which triggers the validation workflow before running your submission code.
Here's Your Updated Working Code
import React from 'react'; import { Form, Field } from "react-final-form"; const sleep = ms => new Promise(resolve => setTimeout(resolve, ms)); // This runs ONLY after validation succeeds const onSubmit = async values => { await sleep(300); try { const response = await fetch('/contact/send', { method: 'POST', headers: { 'Accept': 'application/json, text/plain, */*', 'Content-Type': 'application/json' }, body: JSON.stringify(values), // Use validated values directly }); const data = await response.json(); console.log('Submission successful:', data); // Optional: Reset the form after success using the `reset` function from render prop // reset(); } catch (err) { console.error('Submission failed:', err); } }; export class ContactPage extends React.Component { // No need for constructor or custom handleSubmit anymore! render() { return ( <div className="contact"> <div className="contact__form"> <Form onSubmit={onSubmit} validate={values => { const errors = {}; if (!values.firstName) { errors.firstName = "Required"; } if (!values.subject) { errors.subject = "Required"; } if (!values.email) { errors.email = "Required"; } else if (!values.email.match(/^([a-zA-Z0-9_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/)) { errors.email = "Please enter a valid e-mail address" } if (!values.message) { errors.message = "Required"; } return errors; }} render={({ handleSubmit, submitting }) => ( // Use react-final-form's handleSubmit for native form onSubmit <form onSubmit={handleSubmit}> <Field name="firstName"> {({ input, meta }) => ( <div> <input {...input} type="text" placeholder="Name" /> {meta.error && meta.touched && <span>{meta.error}</span>} </div> )} </Field> <Field name="subject"> {({ input, meta }) => ( <div> <input {...input} type="text" placeholder="Subject" /> {meta.error && meta.touched && <span>{meta.error}</span>} </div> )} </Field> <Field name="email"> {({ input, meta }) => ( <div> <input {...input} type="email" placeholder="E-mail" /> {meta.error && meta.touched && <span>{meta.error}</span>} </div> )} </Field> <Field name="message"> {({ input, meta }) => ( <div> <textarea {...input} placeholder="Message" /> {meta.error && meta.touched && <span>{meta.error}</span>} </div> )} </Field> <div className="buttons"> <button type="submit" disabled={submitting}> Submit </button> </div> </form> )} /> </div> </div> ); } } export default ContactPage;
Key Changes Made:
- Removed the custom
handleSubmitand constructor—react-final-form handles the submission flow now. - Moved your fetch logic into the Form component's
onSubmitfunction, which only runs when validation passes. - Eliminated all refs since react-final-form manages input values in the
valuesobject. - Passed the render prop's
handleSubmitto the native<form>to trigger validation before submission.
内容的提问来源于stack exchange,提问作者akirtovskis
相关产品推荐
相关产品推荐

