Description
Prerequisites
- I have searched the existing issues
- I understand that providing a SSCCE example is tremendously useful to the maintainers.
- I have read the documentation
- Ideally, I'm providing a sample JSFiddle or a shared playground link demonstrating the issue.
What theme are you using?
core
Version
4.2.0
Current Behavior
In my react app, I have a form with a few fields. Two of them use a custom field. What I'm trying to do is that when the 1st one's value changes, the 2nd one should clear.
To do that, I'm passing all the form's data into the form context, and making the 2nd field check when the 1st field's value changes (using useEffect), and call "onChange(null)".
The problem is that sometimes the 2nd field's value doesn't nullify. It would call "onChange(null)" but the "formData" for it does not update, and the field will stay the same.
But, if I put that "onChange(null)" into a setTimeout for 50ms, it works always.
The custom field (simplified):
function AutoCompleteAsync(props: AutocompleteAsyncFieldProps) { // type extends "FieldProps"
const {
id,
formData,
onChange,
customOptions, // [mine] custom options passed
isDependant, // [mine] custom boolean passed to show if this field depends on another (resets when it changes)
formContext,
} = props;
const [localValue, setLocalValue] = useState<string>('');
.... other unrelated states ....
const allFormData = useMemo<Record<string, any>>(
() => formContext?.allFormData || {},
[formContext],
);
// If this field depends on another field, evaluate the dependance field name and value
const [dependsOn, dependsOnEntity, dependanceValue] = useMemo<
[string | null, string | null, string | null]
>(() => {
if (isDependant) {
// "dependsOn" might contain dots (eg "status.key"), so extract "status.key" from allFormData
const extractedValue: string | null = get(
allFormData,
customOptions.asyncData!.dependsOn!,
null,
);
return [
customOptions.asyncData!.dependsOn!,
customOptions.asyncData!.dependsOnEntity!,
extractedValue,
];
}
return [null, null, null];
}, [isDependant, customOptions, allFormData]);
const onValueSelected = useCallback(
(val: string) => {
setLocalValue(val);
onChange(val);
},
[onChange],
);
useEffect(() => {
setLocalValue(formData);
}, [formData]);
// In case this field depends on another, reset it when the dependent field value changes
useEffect(() => {
if (isDependant) {
// !!! HERE IS THE PROBLEM: setTimeout as workaround to make it work
setTimeout(() => {
onChange(null);
}, 50);
}
}, [
isDependant,
dependanceValue,
]);
return (
<Autocomplete
...
value={localValue}
onChange={(ev, newVal) => {
setLocalValue(newVal);
onChange(newVal);
}}
/>
);
}
export default AutoCompleteAsync;
I'm certain that the "onChange(null)" is being called when I need it. Even used the debugger and stepped in. But sometimes it doesn't update the field formData to null when I don't have that setTimeout.
Expected Behavior
When I call "onChange(null)", it should always update the formData instead of just sometimes, without needing to use a setTimeout.
Steps To Reproduce
- Inside a react app
- Initialize a form with 2 custom fields
- Pass in all the form's data into the RJSF component's form context
- In the second custom field, add a useEffect to the form data's 1st field
- In that useEffect, call "onChange(null)" when the 1st field's value changes
- The second field will not update to null sometimes.
Environment
- OS: Windows 11 Pro
- Node: 18.0.0
- npm: 8.6.0
Anything else?
No response