Drag and drop file upload is a user-friendly feature that can significantly enhance the experience of your web application. In this guide, we'll walk through the process of implementing drag and drop file upload functionality in a React application using the HTML5 Drag and Drop API and File API.

Setting up the React component

First, let's create a basic React component that will handle our drag and drop functionality:

import React, { useState, useRef } from 'react'

const DragAndDropUpload = () => {
  const [dragActive, setDragActive] = useState(false)
  const [files, setFiles] = useState([])
  const inputRef = useRef(null)

  // Component JSX will go here

  return <div>{/* Component UI will go here */}</div>
}

export default DragAndDropUpload

Implementing drag and drop event handlers

Next, we'll add event handlers for the drag and drop events:

const handleDrag = (e) => {
  e.preventDefault()
  e.stopPropagation()
  if (e.type === 'dragenter' || e.type === 'dragover') {
    setDragActive(true)
  } else if (e.type === 'dragleave') {
    setDragActive(false)
  }
}

const handleDrop = (e) => {
  e.preventDefault()
  e.stopPropagation()
  setDragActive(false)
  if (e.dataTransfer.files && e.dataTransfer.files[0]) {
    handleFiles(e.dataTransfer.files)
  }
}

const handleFiles = (files) => {
  setFiles(Array.from(files))
  // You can add additional logic here, such as file validation or immediate upload
}

Creating the UI

Now, let's create the UI for our drag and drop area:

return (
  <div
    className={`drag-drop-area ${dragActive ? 'drag-active' : ''}`}
    onDragEnter={handleDrag}
    onDragLeave={handleDrag}
    onDragOver={handleDrag}
    onDrop={handleDrop}
  >
    <input
      type="file"
      ref={inputRef}
      multiple
      onChange={(e) => handleFiles(e.target.files)}
      style={{ display: 'none' }}
    />
    <p>Drag and drop files here or</p>
    <button onClick={() => inputRef.current.click()}>Select Files</button>
    {files.length > 0 && (
      <div>
        <h4>Selected Files:</h4>
        <ul>
          {files.map((file, index) => (
            <li key={index}>{file.name}</li>
          ))}
        </ul>
      </div>
    )}
  </div>
)

Styling the component

To make our drag and drop area visually appealing, we can add some CSS:

.drag-drop-area {
  border: 2px dashed #ccc;
  border-radius: 20px;
  width: 480px;
  font-family: sans-serif;
  margin: 100px auto;
  padding: 20px;
  text-align: center;
}

.drag-drop-area.drag-active {
  background-color: #f0f0f0;
}

.drag-drop-area p {
  margin-top: 0;
}

.drag-drop-area button {
  background-color: #007bff;
  border: none;
  color: white;
  padding: 10px 20px;
  text-align: center;
  text-decoration: none;
  display: inline-block;
  font-size: 16px;
  margin: 4px 2px;
  cursor: pointer;
  border-radius: 5px;
}

Handling file upload

Once files are selected or dropped, you'll want to upload them to your server. Here's a basic example of how you might handle file upload:

const uploadFiles = async () => {
  const formData = new FormData()
  files.forEach((file) => {
    formData.append('files', file)
  })

  try {
    const response = await fetch('your-upload-endpoint', {
      method: 'POST',
      body: formData,
    })
    if (response.ok) {
      console.log('Files uploaded successfully')
      setFiles([]) // Clear the files array after successful upload
    } else {
      console.error('File upload failed')
    }
  } catch (error) {
    console.error('Error uploading files:', error)
  }
}

You can call this uploadFiles function when appropriate, such as when a user clicks an "Upload" button.

Conclusion

By following this guide, you've created a functional drag and drop file upload component in React. This component enhances user experience by providing an intuitive way to select and upload files.

Remember to handle errors gracefully, provide feedback to users during the upload process, and implement any necessary file type or size restrictions based on your application's requirements.

For a more robust file upload solution that handles chunking, resumability, and works great with React, consider checking out Uppy, an open-source file uploader for web browsers developed by Transloadit.