How to use react-dropzone with Remix?

63 views Asked by At

Background

I am trying to use react-dropzone inside of a Remix application to do a standard file upload. I have followed the basic example in the react-dropzone documents, but keep running into the same issue when trying to submit the file in a normal form tag. To validate my back-end strategy, I used a standard <input type="file" /> and it is working as expected leading me to believe my issue is with the react-dropzone implementation.

Questions

  • Does react-dropzone actually use the <input> tag just like normal or is there more processing needed to get the actual files ready for upload?
  • Could this be a mime type issue because I am using the standard Remix server?

Code

// Dropzone component

export default function DropzoneComponent(){
  const {getRootProps, getInputProps, isDragActive, acceptedFiles} = useDropzone()

  const fileList = acceptedFiles.map(f => <p key={f.name}>{f.name}</p>)

  return (
    <div {...getRootProps({className: 'dropzone'})}>
      <input {...getInputProps({name: 'upload-file'})} />

      {fileList.length > 0 ? (
        <div className="filelist">{fileList}</div>
      ) : (
        <CiViewList className="dropzone-icon" />
      )}

      {isDragActive ? (
        <p>Drop here...</p>
      ) : (
        <p>Drag files here or <Button type='button'>Browse</Button>
      )}
    </div>
  )
}
// Remix Route
export async function action({request}: ActionFunctionArgs){
  const uploadHandler = unstable_composeUploadHandlers(
    unstable_createFileUploadHandler({
      maxPartSize: 5_000_000,
      file: ({filename}) => filename,
      directory: './public/uploads'
    }),
    unstable_createMemoryUploadHandler()
  )

  const formData = await unstable_parseMultipartFormData(request, uploadHandler)
  const submission = parseWithZod(formData, {schema})

  // Do other things with file (irrelevant as the submission never makes it past the zod validation)

}


export default UploadRoute(){
  return (
    // ...
    <Form method="POST" encType="multipart/form-data">
      <DropzoneComponent />
      <Button type="submit">Upload</Button>
    </Form>
  )
}

Expected Behavior

  1. Select or drag file into Dropzone area
  2. Submit form just like any other Remix form submission
  3. Parse data in action using the uploadHandler
  4. Validate data using conform and zod
  5. Do further processing with file upload

Actual Behavior

  1. Select file using Dropzone area (appears to work as I can list the file using acceptedFiles)
  2. Submit form as usual (using form submit button)
  3. Parse data using uploadHandler
  4. action fails to store the file and the zod/conform validation also fails

Details

I happen to be uploading .csv files. When doing this with a standard <input type="file" /> and console logging inside of the action for the route, it shows that piece of the FormData to be of the type Blob {size: xxx, type: 'text/csv'} and is then stored into the appropriate file location and passes validation.

When done with react-dropzone it just shows Blob {size: 0, type: 'application/octet-stream'} and is not stored in the file location. I'm assuming it is because the actual file is not being sent with the request, but the documentation is silent on how to submit the file as a standard form input element. I also tried specifying the accept parameter inside the useDropzone hook, but it didn't change the result.

Any help would be appreciated....

0

There are 0 answers