reactjsformsfilereact-hook-formreact-dropzone

react-hook-form - how to handle files array form


im working with react and react-hook-form, to create a form.

in the form, there is files array.

I added useFieldArray to handle the files.

I use replace to add the files to the form-state (+ react-dropzone)

The issue: form.fields contain only sub-object of the files uploaded . but if I do const files = form.watch('files'), files contain the whole file object.

What i need to do in order to see the full object in form.fields and not only on the return value of form.watch('files')

code-sandbox

Expected:

[
   {
      size: 100,
      name: 'file-name'
      path: 'some-path',
      type: 'some-type'
   }
]

Actual:

[
  {
     id: 'some-id',
     path: 'some-path' 
  }
]

Code

  const form = useForm<UploadFormValues>({
    defaultValues: {
             files: [],
             tradingPartyId: '',
             },
    resolver: yupResolver(VALIDATION_SCHEMA),
  });
  const { fields, replace } = useFieldArray({
    control: form.control,
    name: 'files',
  });

  
  const files = form.watch('files');
 
  console.log(fields); // [{ id: 'id', path: 'path'}]
  console.log(files); // [{ path: 'path', size: 100, name: 'name'}]

  const fileUploaderState = useFileUploader({
    onDrop: replace,
    accept: {
      '': ACCEPTED_FILES,
    },
    useFsAccessApi: false,
  });

  <FilesUploader
          uploadFilesTitle='Upload Files'
          fileUploaderState={fileUploaderState}
          displayedFileName={fields.map((file) => file.name).join(', ')}
          style={FILES_UPLOADER_STYLE}
        />

useFileUploader

import { DropzoneOptions, useDropzone } from 'react-dropzone';

export const useFileUploader = (props?: DropzoneOptions) => {
  return useDropzone({
    ...props,
    noClick: true,
  });
};

react-hook-form docs: https://react-hook-form.com/api/usefieldarray


Solution

  • code-sendbox Solution

    Solution:

    change the form state property files structure

    from:

    type UploadFormValues = {
      files: { name: string; size: number; type?: UploadObjectType }[];
      tradingPartyId: string;
    };
    

    to (add file: File):

    type UploadFormValues = {
      files: { file: File; name: string; size: number; type?: UploadObjectType }[];
      tradingPartyId: string;
    };
    

    onDrop

    onDrop: (files) =>
          replace(
            files.map((file) => ({ file, name: file.name, size: file.size })),
          )