1. Via the computed prop in field definitions (constructor)
The computed prop accepts a function ({ field, form }) => .... MRF wraps it internally as a MobX computed: the value re-evaluates automatically whenever its dependencies change.
{
unitPrice: { value: 100, label: 'Unit Price (€)', type: 'number' },
quantity: { value: 3, label: 'Quantity', type: 'number' },
discountPercent: { value: 10, label: 'Discount (%)', type: 'number' },
subtotal: {
computed: ({ form }) =>
Number(form.$('unitPrice').value) * Number(form.$('quantity').value),
label: 'Subtotal (€)',
},
discount: {
computed: ({ form }) => {
const sub = Number(form.$('unitPrice').value) * Number(form.$('quantity').value);
const pct = Number(form.$('discountPercent').value) || 0;
return Number((sub * (pct / 100)).toFixed(2));
},
label: 'Discount (€)',
},
total: {
computed: ({ form }) => {
const sub = Number(form.$('unitPrice').value) * Number(form.$('quantity').value);
const pct = Number(form.$('discountPercent').value) || 0;
return Number((sub - sub * (pct / 100)).toFixed(2));
},
label: 'Total (€)',
},
}
2. Alternative with autorun()
Inside a useEffect you can use MobX autorun()to observe fields and write the result to another field via .set(). It works but is more verbose and requires manual disposer management.
useEffect(() => {
const disposer = autorun(() => {
const sub = Number(form.$('unitPrice').value) * Number(form.$('quantity').value);
form.$('total').set(sub);
});
return () => disposer();
}, []);