Last few days, I was trouble updating form data in an array of arrays in react-form-hook. I have attached the screenshot of my structure of fields, type and etc. I want to update the fields of fields data when I save the data.
I want to perform it with nested array with useFieldArray hooks which came from react-hook-form library.
I'm not getting any error on it but data was not passed correctly in the database. How can I fix it?
export const defects = {
title: 'Defects',
fields: [
{
title: 'Defect Location:',
name: 'defects.location',
type: 'checkbox',
fields: [
{
title: 'Interior',
type: 'checkbox',
name: 'defects.location.interior',
},
{
title: 'Roof space',
type: 'checkbox',
name: 'defects.location.roofSpace',
},
{
title: 'Other',
type: 'textarea',
name: 'defects.location.other',
},
],
},
{
title: 'Defect Summary:',
name: 'defects.summary',
type: 'checkbox',
fields: [
{
title: 'Roof Framing',
type: 'checkbox',
name: 'defects.summary.roofFraming',
},
{
title: 'Porch Support',
type: 'checkbox',
name: 'defects.summary.porchSupport',
},
{
title: 'Alfresco Support',
type: 'checkbox',
name: 'defects.summary.alfrescoSupport',
},
{
title: 'Gate Feature',
type: 'checkbox',
name: 'defects.summary.gateFeature',
},
{
title: 'Subfloor Structure',
type: 'checkbox',
name: 'defects.summary.subfloorStructure',
},
{
title: 'Brick',
type: 'checkbox',
name: 'defects.summary.brick',
},
{
title: 'Other',
type: 'textarea',
},
],
},
],
}
Parent Component
const { register, handleSubmit, errors, setValue, getValues, control, watch, reset } =
useForm({ shouldUnregister: false })
const { fields, append, remove, update } = useFieldArray({
control: control,
name: defects.title,
})
const onSubmit = async (data) => {
const values = getValues()
console.log('data is here', data, values)
const response = await fetch('/api/db/handler', {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(data),
})
if (response.ok) {
setSaved(true)
setTimeout(() => {
setSaved(false)
}, 2000)
}
return response
}
return(
<Defects
data={defects}
register={register}
setValue={setValue}
control={control}
watch={watch}
fields={fields}
append={append}
remove={remove}
update={update}
/>
)
Defect JS
const Defects = ({
register,
setValue,
control,
watch,
data,
fields,
append,
remove,
update,
}) => {
useEffect(() => {
update();
}, [register]);
return (
<div>
{fields.map((props, index) => {
return (
<Disclosure
defaultOpen
open={true}
as='div'
key={props.id}
className='border-b-4 p-4 border-gray-100'
>
{index > 0 ? (
<div className='flex items-center'>
<Disclosure.Button className='text-xl uppercase underline flex items-center'>
{`DEFEECT ${index}`}
<FaChevronDown className='ml-4 ui-open:rotate-180 ui-open:transform' />
</Disclosure.Button>
<button
className='bg-sky-400 text-white px-4 py-2 rounded mt-4 ml-12'
onClick={() => remove(index)}
>
Delete
</button>
</div>
) : (
<div className='flex items-center'>
<Disclosure.Button className='text-xl uppercase underline flex items-center'>
DEFEECTS
<FaChevronDown className='ml-4 ui-open:rotate-180 ui-open:transform' />
</Disclosure.Button>
</div>
)}
{props.fields.map((field, i) => {
return (
<Disclosure.Panel
key={field.title + i}
className='grid grid-cols-[minmax(min-content,.5fr)_minmax(300px,1fr)] my-4'
>
{field.sectionTitle && (
<h3 className='col-span-2 text-lg border-b-4 mb-2 border-b-gray-100 uppercase'>
{field.sectionTitle}
</h3>
)}
<h3>{field.title}</h3>
{field.type == 'checkbox' && (
<Checkbox
data={field}
register={register}
setValue={setValue}
nestedIndex={index}
fieldName={field.name}
fieldIndex={i}
/>
)}
</Disclosure.Panel>
);
})}
</Disclosure>
);
})}
</div>
);
};
Checkbox JS
import React from 'react';
const Checkbox = ({ data,
register,
setValue,
nestedIndex = null,
fieldName = '',
fieldIndex = null,}) => {
return (
<div className='flex flex-col justify-start items-start'>
{data.fields.map((item, index) => {
return (
// eslint-disable-next-line react/jsx-key
<div
key={`${item.title}${index}`}
className='flex flex-row items-center'
>
<label className='mr-2' htmlFor={item.name}>
{item.title}
</label>
<input
type={item.type}
name={`Defects[${nestedIndex}].fields[${fieldIndex}].fields[${index}].${item.name}`}
className={`${
item.type == 'textarea' && 'w-full'
} border border-gray-100 p-2`}
{...register(
`Defects[${nestedIndex}].fields[${fieldIndex}].fields[${index}].${item.name}`
)}
/>
</div>
);
})}
I have passed the instance of useForm's hook to the child components then I have used it in the child components as you see in the checkbox file and it's working correctly now.