DEV Community

Aashutosh Poudel
Aashutosh Poudel

Posted on

11 2

File uploads and validation with React and Formik

Formik doesn't provide a way to handle file uploads easily. I found a decent solution looking at various github issues and stackoverflow discussions.

Here is a codesandbox showing how to validate the size of the files as well as their MIME types.
Link: https://codesandbox.io/s/hardcore-ully-tdk4iu?file=/src/App.js

The basic idea behind working with files in Formik is to make the file input component uncontrolled and access the selected files with a ref. More info here: https://reactjs.org/docs/uncontrolled-components.html#the-file-input-tag

Step 1: We create a ref inside the form and pass that ref to the file input component.

export default function App() {
  const initialValues = {
    files: ""
  };
  const fileRef = useRef(null);
  return (
    <Formik
      initialValues={initialValues}
      validationSchema={Yup.object({
        files: Yup.mixed()
          {/* ... */}
      })}
      onSubmit={(values) => {
        {/* ... */}
      }}
    >
      <Form>
        <FileUpload name="files" fileRef={fileRef} />
        <button type="submit">Submit</button>
      </Form>
    </Formik>
  );
}
Enter fullscreen mode Exit fullscreen mode

Step 2: Inside the <FileUpload> component we use the passed ref as follows:

const FileUpload = ({ fileRef, ...props }) => {
  const [field, meta] = useField(props);
  return (
    <div>
      <label htmlFor="files">Choose files</label>{" "}
      <input ref={fileRef} multiple={true} type="file" {...field} />
      {meta.touched && meta.error ? (
        <div style={{ color: "red" }}>{meta.error}</div>
      ) : null}
    </div>
  );
};
Enter fullscreen mode Exit fullscreen mode

Step 3: We validate the size of files uploaded and the MIME type of the file as follows:
Note: we are accessing the files directly using ref.

validationSchema={Yup.object({
        files: Yup.mixed()
          .test("is-file-too-big", "File exceeds 10MB", () => {
            let valid = true;
            const files = fileRef?.current?.files;
            if (files) {
              const fileArr = Array.from(files);
              fileArr.forEach((file) => {
                const size = file.size / 1024 / 1024;
                if (size > 10) {
                  valid = false;
                }
              });
            }
            return valid;
          })
          .test(
            "is-file-of-correct-type",
            "File is not of supported type",
            () => {
              let valid = true;
              const files = fileRef?.current?.files;
              if (files) {
                const fileArr = Array.from(files);
                fileArr.forEach((file) => {
                  const type = file.type.split("/")[1];
                  const validTypes = [
                    "zip",
                    "xml",
                    "xhtml+xml",
                    "plain",
                    "svg+xml",
                    "rtf",
                    "pdf",
                    "jpeg",
                    "png",
                    "jpg",
                    "ogg",
                    "json",
                    "html",
                    "gif",
                    "csv"
                  ];
                  if (!validTypes.includes(type)) {
                    valid = false;
                  }
                });
              }
              return valid;
            }
          )
      })}
Enter fullscreen mode Exit fullscreen mode

References:

  1. https://github.com/jaredpalmer/formik/issues/926
  2. https://stackoverflow.com/a/55570763/7358595

Heroku

This site is built on Heroku

Join the ranks of developers at Salesforce, Airbase, DEV, and more who deploy their mission critical applications on Heroku. Sign up today and launch your first app!

Get Started

Top comments (0)

A Workflow Copilot. Tailored to You.

Pieces.app image

Our desktop app, with its intelligent copilot, streamlines coding by generating snippets, extracting code from screenshots, and accelerating problem-solving.

Read the docs

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay