Reputation: 1205
I have an array of objects in react-final-form
with a sum
field. At the end I would like to count the total of all sums. So I'm using calculated fields from final-form-calculate
like this:
const calculator = createDecorator({
field: /day\[\d\]\.sum/, // when a field matching this pattern changes...
updates: (value, name, allValues) => {
console.log("Updated field", value, name);
// ...update the total to the result of this function
total: (ignoredValue, allValues) =>
(allValues.day || []).reduce((sum, value) => sum + Number(value || 0), 0);
return {};
}
});
When I enter values in the inputs, console.log
is called, but the total is not updated. I guess it doesn't pick the values from the necessary fields. How can I fix it? Here is my codesandbox https://codesandbox.io/s/react-final-form-calculated-fields-hkd65?fontsize=14.
Upvotes: 0
Views: 1358
Reputation: 1567
Final-form-calculate docs, say the the updater can be:
Either an object of updater functions or a function that generates updates for multiple fields.
In your example, the code was some kind of mix between them. Also value.sum
contains the entered numbers, not value
.
Here's how to do it correctly, with an object of updater functions:
const calculator = createDecorator({
field: /day\[\d\]\.sum/,
updates: {
total: (ignoredValue, allValues) => (allValues.day || []).reduce((sum, value) => sum + Number(value.sum || 0), 0)
}
});
or updates for multiple fields (just one actually, but could be more):
const calculator = createDecorator({
field: /day\[\d\]\.sum/,
updates: (ignoredValue, fieldName, allValues) => {
const total = (allValues.day || []).reduce((sum, value) => sum + Number(value.sum || 0), 0);
return { total };
}
});
Also, here are the updater Typescript definitions, for reference:
export type UpdatesByName = {
[FieldName: string]: (value: any, allValues?: Object, prevValues?: Object) => any
}
export type UpdatesForAll = (
value: any,
field: string,
allValues?: Object,
prevValues?: Object,
) => { [FieldName: string]: any }
export type Updates = UpdatesByName | UpdatesForAll
Upvotes: 1
Reputation: 2573
You have some syntactical error in your code snippet, specifically the calculator function. This version of the function works:
const calculator = createDecorator({
field: /day\[\d\]\.sum/, // when a field matching this pattern changes...
updates: {
// ...update the total to the result of this function
total: (ignoredValue, allValues) => (allValues.day || []).reduce((sum, value) => sum + Number(value.sum || 0), 0),
}
});
There are two major changes I did,
Number(value || 0)
to Number(value.sum || 0)
updates
property to an object instead of a function.Upvotes: 1