3个Redux-form共用单个提交按钮与API的数据提交实现咨询
Got it, let's walk through exactly how to collect data from 3 separate Redux-Form components and submit everything through a single API endpoint. This is super common when you split a big form into smaller, more user-friendly sections—here's a practical, step-by-step solution with code examples you can adapt:
1. Pull in All Form Data to a Parent Container
Each Redux-Form component registers its state under a unique form key in your Redux store. We'll use Redux-Form's built-in selectors to fetch each form's values and validation status in a parent container component.
First, make sure each of your 3 forms has a distinct form name (e.g., userDetails, billingInfo, preferences). Then, in the parent component, use connect to pull in the data from all three forms:
import { connect } from 'react-redux'; import { getFormValues, getFormSyncErrors, touchAll, reset } from 'redux-form'; // ... rest of component code const mapStateToProps = (state) => ({ // Fetch values from each form userDetails: getFormValues('userDetails')(state) || {}, billingInfo: getFormValues('billingInfo')(state) || {}, preferences: getFormValues('preferences')(state) || {}, // Fetch validation errors for each form userErrors: getFormSyncErrors('userDetails')(state) || {}, billingErrors: getFormSyncErrors('billingInfo')(state) || {}, preferenceErrors: getFormSyncErrors('preferences')(state) || {}, }); const mapDispatchToProps = (dispatch) => ({ // Trigger touch on all fields in a form to show validation errors touchAllFields: (formName) => dispatch(touchAll(formName)), // Reset a form after successful submission resetForm: (formName) => dispatch(reset(formName)), });
2. Build a Unified Submit Handler
In the parent component, create a single submit function that:
- Triggers validation for all forms (so users see errors if any fields are missing/invalid)
- Checks if all forms are valid
- Merges all form data into one payload
- Sends the payload to your single API endpoint
Here's how that function might look:
async handleSubmitAll() { const { userDetails, billingInfo, preferences, userErrors, billingErrors, preferenceErrors, touchAllFields, resetForm } = this.props; // Step 1: Trigger validation for all forms touchAllFields('userDetails'); touchAllFields('billingInfo'); touchAllFields('preferences'); // Step 2: Check if any form has validation errors const hasErrors = Object.keys(userErrors).length > 0 || Object.keys(billingErrors).length > 0 || Object.keys(preferenceErrors).length > 0; if (hasErrors) { this.setState({ submitError: 'Please fix all errors in the forms above' }); return; } // Step 3: Merge form data (adjust structure to match your API's requirements) const combinedPayload = { user: userDetails, billing: billingInfo, preferences: preferences }; // Step 4: Submit to API try { this.setState({ isSubmitting: true, submitError: null }); await yourApiCall(combinedPayload); // Replace with your actual API function // Reset all forms after success resetForm('userDetails'); resetForm('billingInfo'); resetForm('preferences'); this.setState({ isSubmitting: false }); // Add success feedback (e.g., alert, toast) } catch (err) { this.setState({ isSubmitting: false, submitError: err.message || 'Failed to submit your data' }); } }
3. Add a Single Submit Button in the Parent
Place your submit button in the parent component, tied to the handler we just built. Disable it while submitting to prevent duplicate requests:
render() { const { isSubmitting, submitError } = this.state; return ( <div className="form-container"> {/* Render your 3 Redux-Form components here */} <UserDetailsForm /> <BillingInfoForm /> <PreferencesForm /> {/* Show error message if submission fails */} {submitError && <div className="error-message">{submitError}</div>} {/* Single submit button */} <button onClick={this.handleSubmitAll} disabled={isSubmitting} className="submit-btn" > {isSubmitting ? 'Submitting...' : 'Submit All Data'} </button> </div> ); }
4. Key Notes to Avoid Issues
- Field Name Conflicts: If your forms share field names (e.g.,
emailin two forms), wrap each form's data in a nested object (like we did withuser,billingin the payload) to avoid overwriting values. - Async Validation: If you use async validation in any form, add checks for
getFormAsyncErrorsandgetFormAsyncValidatinginmapStateToPropsto ensure async validation completes before submitting. - Redux Store Setup: Double-check that you've added Redux-Form's reducer to your root reducer:
import { combineReducers } from 'redux'; import { reducer as formReducer } from 'redux-form'; const rootReducer = combineReducers({ form: formReducer, // your other reducers });
内容的提问来源于stack exchange,提问作者Akash Bambhaniya

