loading...
Cover image for Multiple file inputs with one submit button with React Hooks

Multiple file inputs with one submit button with React Hooks

fadiamg profile image Fadi Updated on ・3 min read

Recently, I was working on a project and I had to make multiple file inputs. The thing is every input should take only one file with certain type which in my case was pdf , jpeg only. After uploading the file, user should submit all the uploaded files together using only one submit button. In my case, user doesn't have to upload all the files at once.

The first thing came to my mind is to use FormData; however, I had to submit an Array of objects each object should have file_Id and the file itself and let's call it uploaded_file in our example. With FormData I couldn't do that, so I had make it in my own way.

I assume in this example that you are familiar with Reactjs and hooks.

Here are the steps I followed to achieve my goal:

1. Create React component with 3 input files, each input file accepts only pdf , jpeg with unique Id. Also, we want 1 submit button.

import React from 'react';

const MultipleFileInput = () => {
  return (
    <form className="upload--container">
      <div className="upload--button">
        <input id={1} accept=".jpeg, .pdf" type="file" />
      </div>
      <div className="upload--button">
        <input id={2} accept=".jpeg, .pdf" type="file" />
      </div>
      <div className="upload--button">
        <input id={3} accept=".jpeg, .pdf" type="file" />
      </div>
      <button type="submit">Submit</button>
    </form>
  );
};

export default MultipleFileInput;

2. create state that will hold the Array of objects.

  // state that will hold the Array of objects
  // initialized with empty array
  const [files, setFiles] = useState([]);

3. Add onChageHandler for each input file. To read these files I have used FileReader Read More About FileReader Web API

// onChange function that reads files on uploading them
// files read are encoded as Base64
  function onFileUpload(event) {
    event.preventDefault();
    // Get the file Id
    let id = event.target.id;
    // Create an instance of FileReader API
    let file_reader = new FileReader();
    // Get the actual file itself
    let file = event.target.files[0];
    file_reader.onload = () => {
    // After uploading the file
    // appending the file to our state array
    // set the object keys and values accordingly
      setFiles([...files, { file_id: id, uploaded_file: file_reader.result }]);
    };
   // reading the actual uploaded file
    file_reader.readAsDataURL(file);
  }

4. now let's implement our submit button, for this example we will just console log the results; however, I had to send these files to the server.

  // handle submit button for form
  function handleSubmit(e) {
    e.preventDefault();
    console.log(files)
  }

5. Finally, Let's add some restrictions to our logic. For example, disable submit button if no file was uploaded.

// button state whether it's disabled or enabled
  const [enabled, setEnabled] = useState(false);
  // using useEffect we can detect if user uploaded any file, 
  // so enable submit button
  useEffect(() => {
    if (files.length === 0) {
      setEnabled(false);
    } else {
      setEnabled(true);
    }
  }, [files]);
// render submit button based on its state. 
{enabled ? (
        <button type="submit">Submit</button>
      ) : (
        <button disabled type="submit">
          Submit
        </button>
 )}

This will be the whole code after all.

codesandox Link


import React, { useState, useEffect } from 'react';

const MultipleFileInput = () => {
  // state that will hold the Array of objects
  // initialized with empty array
  const [files, setFiles] = useState([]);
  // onChange function that reads files on uploading them
  // files read are encoded as Base64
  function onFileUpload(event) {
    event.preventDefault();
    // Get the file Id
    let id = event.target.id;
    // Create an instance of FileReader API
    let file_reader = new FileReader();
    // Get the actual file itself
    let file = event.target.files[0];
    file_reader.onload = () => {
      // After uploading the file
      // appending the file to our state array
      // set the object keys and values accordingly
      setFiles([...files, { file_id: id, uploaded_file: file_reader.result }]);
    };
    // reading the actual uploaded file
    file_reader.readAsDataURL(file);
  }
  // handle submit button for form
  function handleSubmit(e) {
    e.preventDefault();
    console.log(files);
  }
  // button state whether it's disabled or enabled
  const [enabled, setEnabled] = useState(false);
  // using useEffect we can detect if user uploaded any file,
  // so enable submit button
  useEffect(() => {
    if (files.length === 0) {
      setEnabled(false);
    } else {
      setEnabled(true);
    }
  }, [files]);

  return (
    <form onSubmit={handleSubmit} className="upload--container">
      <h1> Multiple File Inputs with Signle Submit Button </h1>
      <div className="upload--button">
        <input
          onChange={onFileUpload}
          id={1}
          accept=".jpeg, .pdf"
          type="file"
        />
      </div>
      <div className="upload--button">
        <input
          onChange={onFileUpload}
          id={2}
          accept=".jpeg, .pdf"
          type="file"
        />
      </div>
      <div className="upload--button">
        <input
          onChange={onFileUpload}
          id={3}
          accept=".jpeg, .pdf"
          type="file"
        />
      </div>
      {enabled ? (
        <button type="submit">Submit</button>
      ) : (
        <button disabled type="submit">
          Submit
        </button>
      )}
    </form>
  );
};

export default MultipleFileInput;

Final Words,

I will be glad if someone shared different approach, or any modifications to my current implementation. So, please don't hesitate to share your thoughts.

Posted on by:

fadiamg profile

Fadi

@fadiamg

Tech enthusiast with big appetite to learn new things every day!

Discussion

markdown guide
 

Great! I will give it a try in my next project.

 

Cool!
Let me know if you needed any help my friend.

 

That's great!!
That must have taken you a lot of search

 

Yeah it did, but it was worth it.
Thank you <3

 

Hey dude, thanks for that. I started learn react this month and I understand you code and your article. Great!