I have a custom field which is a calculated value that depends on 2 sibling fields. The following function uses setValue to populate that field inside of a useEffect function with siblings as dependencies.
If I manually change that field (which at times I would like to), it persists to the database with the overwritten value, but upon page refresh it shows the calculated field since the useEffect runs on load. Is there a way in payload to make it effect only if a sibling value is changed manually and not on load? is useEffect the correct way to do it?
import React, { useEffect } from "react";
import {
useField,
useAllFormFields,
reduceFieldsToValues,
Label,
TextInput,
} from "payload/components/forms";
import { Props } from "payload/components/fields/Text";
export const CustomOutgoingPayment: React.FC<Props> = ({
path,
label,
name,
}) => {
const { value, setValue } = useField<string>({ path });
const [fields] = useAllFormFields();
const formData = reduceFieldsToValues(fields, true);
const calculationFunction = () => {
let calculatedOutgoingPayment =
formData?.incomingPayment -
formData?.incomingPayment * (formData?.calculationPercentage / 100);
setValue(calculatedOutgoingPayment);
};
useEffect(() => {
calculationFunction();
}, [formData.incomingPayment, formData.calculationPercentage]);
return (
<>
<Label label={label} />
<TextInput
value={value !== undefined ? value : ""}
name={name}
path="OutgoingPaymentField"
onChange={(e) => setValue(e.target.value)}
/>
</>
);
};
I suppose it became more of a React question. I managed to solve this by changing the useEffect() to use the mount pattern with a custom hook. Code is as follows:
Replace the useEffect with the following:
const useEffectAfterMount = (cb, dependencies) => {
const mounted = useRef(true);
useEffect(() => {
if (!mounted.current) {
return cb();
}
mounted.current = false;
}, dependencies);
};
useEffectAfterMount(() => {
calculationFunction();
}, [formData.incomingPayment, formData.calculationPercentage]);
Star
Discord
online
Get help straight from the Payload team with an Enterprise License.