Problem
I want to implement key/value pairs of input fields in a form that can be added by a user.
In addition, I want to display saved data when the user has submitted the form and the page is displayed again.
Preconditions
- I'm using
react-hook-form V7(RHF) and itsuseFieldArrayhook. - As I use Material-UI I have to use
controlled components.
Working solution
In a simplified app, I have a parent component using the useForm hook and two child components, one for the purpose of demonstration holding normal form fields and an <ArrayFields /> component holding the array fields.
Yesterday I learned by this answer that one way to do it is to set the defaultValues object in the parent's useForm hook like this:
const methods = useForm({
defaultValues: {
email: "john.smith@example.com",
firstName: "John",
lastName: "Smith",
systemRole: "Admin",
envRoles: [ // <-- saved dynamic fields
{ envName: "foo1", envRole: "bar1" },
{ envName: "foo2", envRole: "bar2" }
]
}
});
Here you can see a codesandbox of this working solution.
Question
Nonetheless, I am wondering if it isn't possible to set the defaultValues in the <ArrayFields /> child component?
useFormContext approach
For example like this using the useFormContext hook:
//
const ArrayFields = ({ fieldset }) => {
const { control, getValues } = useFormContext({
defaultValues: {
envRoles: [
{ envName: "foo1", envRole: "bar1" },
{ envName: "foo2", envRole: "bar2" }
]
}
});
const { fields, append, remove } = useFieldArray({
control,
name: "envRoles"
});
...
}
- But this is not displaying the saved fields at all
- See here a codesandbox version of the useFormContext approach
Props approach
Next, I tried to pass the fields (alias envRoles) as props and set the defaultValues to the Controller directly
// index.js:30
<ArrayFields
fieldset={[
{ envName: "foo1", envRole: "bar1" },
{ envName: "foo2", envRole: "bar2" }
]}
/>
// ArrayFields.js:35
<Controller
render={({ field }) => <input {...field} />}
defaultValue={item.envName} {/* <-- defaultValue on Controller */}
name={`envRoles[${index}].envName`}
control={control}
/>
- This displays the
defaultValues - but does not work when clicking on the add or delete button
- See this codesandbox of the props approach
Question again
So is it really true that RHF does not allow handling all things that matter to the component inside this component?
Thanks in advance for your hints.