I'm using a DynamicForm component with a ref in a React functional component. I want to update the form once my Firebase collection is loaded. Here’s the relevant part of my component:
const dynamicFormRef = useRef(null);
const { firebaseCollection } = useGetFirebaseCollection(firebaseCollectionName().trucks);
useEffect(() => {
if (firebaseCollection && dynamicFormRef.current) {
dynamicFormRef.current.setFormData((prevFormData) => ({
...prevFormData,
truckId: {
...prevFormData.truckId,
options: firebaseCollection.map((truck) => truck.nrAuto),
},
}));
}
}, [firebaseCollection, dynamicFormRef.current]);
return (
<DynamicForm
ref={dynamicFormRef}
fields={truckDocumentDatabaseSchema().fields}
mode="add"
onSubmit={submitData}
/>
)
It runs well, but ESLint complains:
React Hook useEffect has an unnecessary dependency: 'dynamicFormRef.current'. Either exclude it or remove the dependency array. Mutable values like 'dynamicFormRef.current' aren't valid dependencies because mutating them doesn't re-render the component react-hooks/exhaustive-deps
So, I try to remove it from the useEffect's dependency array, he useEffect does not run when I expect it to.
I suspect that firebaseCollection is loaded before DynamicForm is rendered, so when the useEffect first runs, dynamicFormRef.current is null. But I’m not entirely sure.
Note: DynamicForm exposes setFormData via useImperativeHandle:
const DynamicForm = forwardRef(
(
{ fields, onSubmit, mode, ...otherProps },
ref
) => {
const [formData, setFormData] = useState(fields);
const [isEditable, setIsEditable] = useState(mode === "add");
// form logic ...
useImperativeHandle(ref, () => ({
submitForm: () => handleFormSubmit(),
isLoading: () => loading,
isEditable: isEditable,
setFormData: setFormData,
}));
return (
<FullBox>
<Box component="form" onSubmit={handleFormSubmit}>
{Object.entries(formData).map(([fieldName, fieldData]) => (
<FieldRenderer
key={fieldName}
fieldName={fieldName}
fieldData={fieldData}
formData={formData}
isEditable={isEditable}
handleChange={handleChange}
/>
))}
</Box>
</FullBox>
);
});
export default DynamicForm;
How do I solve this? If I want it to work, the linter complains; if I want the linter to be happy, the useEffect doesn't do its job. I thought I understood (at least in principle) what refs are, but it seems there are some gaps in my understanding.