In React-dropzone, how to tell the user the file's maxSize is too big?

AnApprentice picture AnApprentice · Jun 26, 2017 · Viewed 7.6k times · Source

I am using the following to allow a user to upload a profile photo with react-dropzone:

const FILE_FIELD_NAME = 'files';

const renderDropzoneInput = (field) => {
  const files = field.input.value;
  let dropzoneRef;
  return (
    <div>
      <Dropzone
        name={field.name}
        onDrop={( filesToUpload, e ) => field.input.onChange(filesToUpload)}
        ref={(node) => { dropzoneRef = node; }}
        accept="image/jpeg, image/png"
        maxSize={5242880}
      >
        {({ isDragActive, isDragReject, acceptedFiles, rejectedFiles }) => {
          if (isDragActive) {
            return "This file is authorized";
          }
          if (isDragReject) {
            return "This file is not authorized";
          }
          return acceptedFiles.length || rejectedFiles.length
            ? `Accepted ${acceptedFiles.length}, rejected ${rejectedFiles.length} files`
            : "Try dropping some files.";
        }}
      </Dropzone>

      <button type="button" onClick={() => { dropzoneRef.open() }}>Open File Dialog</button>

      {field.meta.touched &&
        field.meta.error &&
        <span className="error">{field.meta.error}</span>}
      {
        files && Array.isArray(files) && (
        <ul>
          { files.map((file, i) =>
            <li key={i}>
              <img key={i} style={{width: 50, height: 50}} src={file.preview} alt="preview" />
              {file.name}
            </li>
          )}
        </ul>
      )}
    </div>
  );
}

... inside my redux-form:

    <div>
      <label htmlFor={FILE_FIELD_NAME}>Files</label>
      <Field
        name={FILE_FIELD_NAME}
        component={renderDropzoneInput}
      />
    </div>

React-dropzone is currently respecting the maxSize, where it rejects files that are over 5megs. The problem is react-dropzone is not telling the user the file is too big.

How can I update the above to tell the user if the file exceeds the maxSize allowed?

Answer

Tom Bombadil picture Tom Bombadil · Sep 5, 2020
import React, { useState } from "react";
import { useDropzone } from "react-dropzone";

const UploadFile = () => {
  const [errors, setErrors] = useState("");

  const { getRootProps, getInputProps } = useDropzone({
    multiple: false,
    onDrop: (acceptedFiles, fileRejections) => {
      fileRejections.forEach((file) => {
        file.errors.forEach((err) => {
          if (err.code === "file-too-large") {
            setErrors(`Error: ${err.message}`);
          }

          if (err.code === "file-invalid-type") {
            setErrors(`Error: ${err.message}`);
          }
        });
      });
    }

  return (
    <div{...getRootProps()}>
      <input {...getInputProps()} title={title} />
        <p style={{ color: "red", padding: 5, margin: 0, fontSize: 14 }}>
          {errors}
        </p>
    </div>
  );
};
  1. Create a useState for errors as above.

  2. onDrop provides a second array argument 'fileRejections'.

  3. Loop through fileRejections to access the errors array in it.

  4. Then, loop through the errors array to access 'code and 'message'.

  5. Check the error code with if else for 'file-too-large' or 'file-invalid-type'. Which are the most common error codes.

  6. Use setState in the if else block to set the err.message to the error state.

  7. Display the error state in 'p' tags inside your dropzone's main div.

This works very well when multiple is set 'false'. For multiple file errors you will have to use an arrayState I guess. I haven't really looked into it.