šŸŽ Checkout my Learn React by Making a Game course and get 1 month Free on Skillshare!

React upload multiple files

Let's see how we can upload multiple files in React by using a mix of FormData() interface and the Fetch API.

If you prefer the video format you can checkout the youtube I've made for this tutorial:

In this example, we want to build React app that uploads a few files and shows a busy indicator the files are sent to the server. Below is the final app in action (the HD version is here):

React upload multiple files example

And here is the full code for it:

import {useState} from 'react'

const API_URL = 'https://httpbin.org/post'
const API_METHOD = 'POST'
const STATUS_IDLE = 0
const STATUS_UPLOADING = 1

const App = () => {
    const [files, setFiles] = useState([])
    const [status, setStatus] = useState(STATUS_IDLE)

    const uploadFiles = (data)=> {
        setStatus(STATUS_UPLOADING)

        fetch(API_URL, {
            method: API_METHOD,
            body: data,
        })
        .then((res) => res.json())
        .then((data) => console.log(data))
        .catch((err) => console.error(err))
        .finally(() => setStatus(STATUS_IDLE))
    }

    const packFiles = (files)=> {
        const data = new FormData()
        [...files].forEach((file, i) => {
            data.append(`file-${i}`, file, file.name)
        })
        return data
    }

    const handleUploadClick = () => {
        if (files.length) {
            const data = packFiles(files)
            uploadFiles(data)
        }
    }

    const renderFileList = () => (<ol>
        {[...files].map((f, i) => (
            <li key={i}>{f.name} - {f.type}</li>
        ))}
    </ol>)

    const getButtonStatusText = () => (
        (status === STATUS_IDLE) ? 
            'Send to server' : 
            <img src = "./load.svg" />
    )

    return (<div>
        <input
            type="file"
            accept="image/*" 
            multiple
            onChange={(e)=> setFiles(e.target.files)} />
        {renderFileList()}
        <button 
            onClick={handleUploadClick} 
            disabled={status === STATUS_UPLOADING}>
                {getButtonStatusText()}
        </button>
    </div>)
}

The whole magic of the example happens in packFiles(), where we use the FormData.append() method to wrap all the files into one single entity that is sent via a fetch request.

If you want to dive more into the FormData interface I've written two articles about it:

We are using the HttpBin service as a dummy endpoint placeholder. After receiving the request it just outputs back a JSON object where we can see the uploaded items in the files property.
React upload multiple files
The file uploader was customized so that it allows the section of multiple files and it takes only images as inputs. You can use the multiple and accept attributes to change these behaviors.
React upload multiple files

The actual files state variable is not an array, but it's iterable, so we can use the spread operator to get an array of files:

const renderFileList = () => (<ol>
  {[...files].map((f, i) => (
    <li key={i}>{f.name} - {f.type}</li>
  ))}
</ol>)

As a final note, you can use the URL.createObjectURL() to make image previews for the uploaded files.

You can see here the GitHub repo for this example, and here is the live working app.

šŸ“– 50 Javascript, React and NextJs Projects

Learn by doing with this FREE ebook! Not sure what to build? Dive in with 50 projects with project briefs and wireframes! Choose from 8 project categories and get started right away.

šŸ“– 50 Javascript, React and NextJs Projects

Learn by doing with this FREE ebook! Not sure what to build? Dive in with 50 projects with project briefs and wireframes! Choose from 8 project categories and get started right away.


Leave a Reply

Your email address will not be published. Required fields are marked *