Redux-form FieldArray中total字段值求和方案咨询
Got it, let's break down how to calculate the sum of total fields from a dynamic FieldArray in React Final Form. The key here is that you don't need to target each index explicitly—you can grab the entire array of items and compute the sum directly. Here are a few reliable approaches:
方法1:使用form.getValues()实时计算
The form object (available via the useForm hook or passed in the render prop of the Form component) lets you fetch the entire test array at once. Pair this with useMemo to avoid recalculating on every render unless the array changes.
import { Form, FieldArray, useForm } from 'react-final-form'; import React from 'react'; function DynamicSumForm() { const form = useForm(); // Memoize the total to optimize performance const testTotal = React.useMemo(() => { // Get the entire test array, default to empty array if it doesn't exist const testItems = form.getValues('test') || []; // Reduce the array to sum up all total values (handle empty/non-number cases) return testItems.reduce((accumulator, item) => { const numericTotal = Number(item.total); return accumulator + (isNaN(numericTotal) ? 0 : numericTotal); }, 0); }, [form]); return ( <Form initialValues={{ test: [{ total: 0 }] }} onSubmit={(values) => { console.log('Submitted values:', values); console.log('Calculated total:', testTotal); }} render={({ handleSubmit }) => ( <form onSubmit={handleSubmit}> <FieldArray name="test"> {({ fields }) => ( <div> {fields.map((name, index) => ( <div key={name} className="item-row"> <label>Item {index + 1} Total:</label> <Field name={`${name}.total`} type="number" placeholder="0" /> <button type="button" onClick={() => fields.remove(index)} disabled={fields.length === 1} > Remove </button> </div> ))} <button type="button" onClick={() => fields.push({ total: 0 })}> Add New Item </button> </div> )} </FieldArray> <div className="total-display"> <strong>Total Sum:</strong> {testTotal} </div> <button type="submit">Submit Form</button> </form> )} /> ); }
方法2:使用formValueSelector获取整个数组
You mentioned formValueSelector works well for explicit fields—good news: it can also fetch the entire test array. Just pass the root array name (test) to the selector, then process the array to calculate the sum.
import { Form, FieldArray, formValueSelector, useFormState } from 'react-final-form'; import React from 'react'; // Create a selector tied to your form (use the Form's `name` prop if you set one) const formSelector = formValueSelector('dynamic-sum-form'); function TotalDisplay() { // Get the current form state const formState = useFormState(); // Fetch the entire test array from form state const testItems = formSelector(formState, 'test') || []; const testTotal = testItems.reduce((sum, item) => { const total = Number(item.total); return sum + (isNaN(total) ? 0 : total); }, 0); return <p><strong>Total:</strong> {testTotal}</p>; } // Use TotalDisplay inside your Form component function MyForm() { return ( <Form name="dynamic-sum-form" initialValues={{ test: [{ total: 0 }] }} onSubmit={(values) => console.log(values)} render={({ handleSubmit }) => ( <form onSubmit={handleSubmit}> <FieldArray name="test"> {/* ... your field array items ... */} </FieldArray> <TotalDisplay /> <button type="submit">Submit</button> </form> )} /> ); }
关键注意事项
- Handle empty/non-number values: Always convert
item.totalto a number and check forNaN—this prevents unexpected NaN results if the field is empty or has non-numeric input. - Memoization: Use
useMemo(in function components) to avoid recalculating the sum on every render, which improves performance especially with large arrays. - Form state updates: Both methods will automatically update the sum whenever the
testarray changes (when you add/remove items or edit atotalfield), since they depend on form state.
内容的提问来源于stack exchange,提问作者Shawn Matthews

