如何在Redux Form中实现两字段onChange求和并显示在第三字段
Hey there! Let's sort out this real-time sum issue you're facing with Redux-Form. The problem you described—where entering 12 + 13 gives 27 instead of 25—happens because your global variable was accumulating every intermediate input value (e.g., when typing "12", it adds 1 first, then 12, same for "13"). Instead of relying on a global variable, we need to pull the current full values of both fields every time either changes, then recalculate the sum from scratch.
Here's a step-by-step solution:
1. Use Redux-Form's Selectors to Get Field Values
First, we'll use formValueSelector to fetch the latest values of clientIncome and partnerIncome from the Redux store. This ensures we always have the complete current value of each field, not just the incremental input.
2. Recalculate Sum on Field Change
Whenever either field updates, we'll take their current values, convert them to numbers, sum them, and update the total field using Redux-Form's change action.
Full Code Example
import React, { Component } from 'react'; import { Field, reduxForm, formValueSelector, change } from 'redux-form'; import { connect } from 'react-redux'; // Replace with your actual form name const FORM_NAME = 'incomeForm'; class IncomeForm extends Component { // Calculate total and update the total field updateTotal = () => { const { clientIncome, partnerIncome, dispatch } = this.props; // Convert values to numbers, default to 0 if empty/non-numeric const clientNum = parseFloat(clientIncome) || 0; const partnerNum = parseFloat(partnerIncome) || 0; const total = clientNum + partnerNum; // Dispatch action to update the totalIncome field dispatch(change(FORM_NAME, 'totalIncome', total.toString())); }; // Trigger recalculation whenever either income field changes componentDidUpdate(prevProps) { const { clientIncome, partnerIncome } = this.props; if (clientIncome !== prevProps.clientIncome || partnerIncome !== prevProps.partnerIncome) { this.updateTotal(); } } render() { return ( <form> <div> <label>Client Income</label> <Field name="clientIncome" component="input" type="number" placeholder="Enter client income" /> </div> <div> <label>Partner Income</label> <Field name="partnerIncome" component="input" type="number" placeholder="Enter partner income" /> </div> <div> <label>Total Income</label> <Field name="totalIncome" component="input" type="text" disabled // Make total field read-only /> </div> </form> ); } } // Selector to get current field values from the store const selector = formValueSelector(FORM_NAME); const mapStateToProps = state => ({ clientIncome: selector(state, 'clientIncome'), partnerIncome: selector(state, 'partnerIncome'), }); // Connect form and Redux store export default connect(mapStateToProps)(reduxForm({ form: FORM_NAME })(IncomeForm));
Key Notes:
- No Global Variables: We avoid global state by pulling values directly from the Redux store, which holds the latest complete values of each form field.
- Robust Number Handling: Using
parseFloat(...) || 0ensures empty inputs or non-numeric values don't break the calculation (they'll be treated as 0). - Real-Time Updates: The
componentDidUpdatelifecycle method triggers the sum recalculation whenever either income field changes, which works perfectly withonChange(since Redux-Form updates the store on every keystroke).
Alternatively, if you prefer handling it directly in the Field's onChange prop (instead of componentDidUpdate), you can modify each field like this:
<Field name="clientIncome" component="input" type="number" onChange={(e, newValue) => { // First update the field's value in the store this.props.input.onChange(newValue); // Then recalculate the total this.updateTotal(); }} />
This achieves the same result—pick whichever approach feels cleaner for your codebase!
内容的提问来源于stack exchange,提问作者Polly Banerjee

