When you add a modern file upload Dropzone in React.js, you give people a clean and intuitive way to drag and drop files instead of wrestling with a tiny upload button. In this guide on Building a Modern File Upload Dropzone in React with Drag and Drop, you will create a smooth react drag and drop file upload area that works well on both desktop and mobile.
We will walk through what a dropzone is, when it makes sense to use it, and then build a simple react dropzone file upload example. By the end, you will know how to use react dropzone in React JS and how to turn that knowledge into a reusable component for your own projects.
What Is a Dropzone and Why Is It Used?
A file upload using dropzone is a specific area on a page where users can drag files from their computer and drop them to begin an upload. It is also clickable to open the file picker, but the drag-and-drop action feels more natural and intuitive.
This design is very popular in modern applications. Users upload profile pictures with it and add documents in project management tools. People also share images and PDFs using a dropzone instead of a simple file input. In a React.js application, developers build a dropzone as a component that listens for drag events, shows visual feedback when files are dragged over it, and captures files when they are dropped. With very little code, a basic file input becomes a modern and intuitive experience.
Developers use the Dropzone JS library because it improves usability and makes applications feel modern and professional. For beginners, libraries like react-dropzone hide complex browser drag events and provide an easy-to-use hook or component. This makes it simple to add reliable drag-and-drop file uploads without extra complexity.
Setting Up a React Drag and Drop File Uploader Component
To build a flexible React JS drag and drop file uploader component, you can use the popular react-dropzone package. It wraps the lower-level drag events and gives you a friendly hook called useDropzone.
Install it in your React project:
npm install react-dropzone
Now create a basic dropzone component. This version lets users drag or click to select files and then logs them, which already covers the core of a react drag and drop file upload feature.
Create the Dropzone Component
Create a file FileDropzone.jsx and add this code. It supports multiple files, basic type filtering, removal, and a dummy upload handler you can connect to your backend.
import React, { useCallback, useState } from 'react'
import { useDropzone } from 'react-dropzone'
function FileDropzone() {
const [files, setFiles] = useState([])
const [isUploading, setIsUploading] = useState(false)
const [error, setError] = useState('')
const onDrop = useCallback(acceptedFiles => {
if (!acceptedFiles.length) {
return
}
const mapped = acceptedFiles.map(file => ({
id: `${file.name}-${file.lastModified}-${file.size}`,
file
}))
setFiles(previous => [...previous, ...mapped])
setError('')
}, [])
const {
getRootProps,
getInputProps,
isDragActive,
isDragReject
} = useDropzone({
onDrop,
multiple: true,
accept: {
'image/*': ['.jpg', '.jpeg', '.png'],
'application/pdf': ['.pdf']
},
maxSize: 5 * 1024 * 1024
})
const handleRemove = id => {
setFiles(current => current.filter(item => item.id !== id))
}
const handleUpload = async () => {
if (!files.length || isUploading) {
return
}
setIsUploading(true)
setError('')
try {
const formData = new FormData()
files.forEach(item => {
formData.append('files', item.file)
})
await fetch('/api/upload', {
method: 'POST',
body: formData
})
setFiles([])
} catch (e) {
setError('Upload failed. Please try again.')
} finally {
setIsUploading(false)
}
}
return (
<section className="fdz-wrapper">
<div
{...getRootProps({
className: `fdz-dropzone ${
isDragActive ? 'fdz-dropzone-active' : ''
} ${isDragReject ? 'fdz-dropzone-reject' : ''}`,
role: 'button',
tabIndex: 0,
'aria-label': 'File upload area. Drag and drop files or click to browse.'
})}
>
<input {...getInputProps()} />
<h2 className="fdz-title">Upload your files</h2>
{isDragReject ? (
<p className="fdz-message">
These files are not allowed. Please drop images or PDF documents.
</p>
) : isDragActive ? (
<p className="fdz-message">Release to drop your files here.</p>
) : (
<p className="fdz-message">
Drag and drop images or PDFs here, or click to choose from your device.
</p>
)}
<p className="fdz-hint">
Accepted: JPG, PNG, PDF. Max size 5 MB per file.
</p>
</div>
{files.length > 0 && (
<div className="fdz-list">
<div className="fdz-list-header">
<h3>Files ready to upload</h3>
<span>{files.length} selected</span>
</div>
<ul className="fdz-items">
{files.map(item => (
<li key={item.id} className="fdz-item">
<div className="fdz-item-info">
<span className="fdz-item-name">{item.file.name}</span>
<span className="fdz-item-meta">
{(item.file.size / 1024).toFixed(1)} KB
</span>
</div>
<button
type="button"
className="fdz-remove"
onClick={() => handleRemove(item.id)}
>
Remove
</button>
</li>
))}
</ul>
<button
type="button"
className="fdz-upload"
onClick={handleUpload}
disabled={isUploading}
>
{isUploading ? 'Uploading...' : 'Upload files'}
</button>
{error && <p className="fdz-error">{error}</p>}
</div>
)}
</section>
)
}
export default FileDropzone
This component gives you a clean react dropzone file upload example that you can reuse across different pages and projects.
Use the Component in Your App
In App.jsx (or App.js), render the dropzone:
import React from 'react'
import FileDropzone from './FileDropzone'
import './file-dropzone.css'
function App() {
return (
<main className="app-root">
<h1>Building a Modern File Upload Dropzone in React with Drag and Drop</h1>
<p>
This simple Dropzone in React.js shows how a modern react drag and drop file upload can feel effortless for your users.
</p>
<FileDropzone />
</main>
)
}
export default App
Create file-dropzone.css and style the component in a way that feels familiar to most React projects.
.app-root {
max-width: 720px;
margin: 40px auto;
padding: 0 16px;
font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
color: #111827;
}
.app-root h1 {
font-size: 1.8rem;
margin-bottom: 8px;
}
.app-root p {
margin-bottom: 20px;
color: #4b5563;
}
.fdz-wrapper {
display: flex;
flex-direction: column;
gap: 16px;
}
.fdz-dropzone {
border: 2px dashed #4f46e5;
border-radius: 14px;
padding: 32px 24px;
background-color: #f9fafb;
text-align: center;
cursor: pointer;
transition: border-color 0.2s ease, background-color 0.2s ease, transform 0.1s ease;
outline: none;
}
.fdz-dropzone-active {
border-color: #2563eb;
background-color: #eff6ff;
transform: scale(1.01);
}
.fdz-dropzone-reject {
border-color: #b91c1c;
background-color: #fef2f2;
}
.fdz-title {
font-size: 1.1rem;
margin-bottom: 4px;
}
.fdz-message {
margin: 6px 0;
color: #111827;
}
.fdz-hint {
margin-top: 8px;
font-size: 0.85rem;
color: #6b7280;
}
.fdz-list {
background-color: #ffffff;
border-radius: 12px;
padding: 16px 20px;
box-shadow: 0 12px 30px rgba(15, 23, 42, 0.08);
}
.fdz-list-header {
display: flex;
justify-content: space-between;
align-items: baseline;
margin-bottom: 10px;
}
.fdz-list-header h3 {
font-size: 1rem;
}
.fdz-list-header span {
font-size: 0.85rem;
color: #6b7280;
}
.fdz-items {
list-style: none;
padding: 0;
margin: 0;
}
.fdz-item {
display: flex;
justify-content: space-between;
align-items: center;
padding: 6px 0;
gap: 10px;
}
.fdz-item + .fdz-item {
border-top: 1px solid #e5e7eb;
}
.fdz-item-info {
display: flex;
flex-direction: column;
}
.fdz-item-name {
font-size: 0.95rem;
}
.fdz-item-meta {
font-size: 0.8rem;
color: #6b7280;
}
.fdz-remove {
border: none;
background-color: transparent;
color: #b91c1c;
font-size: 0.85rem;
cursor: pointer;
}
.fdz-remove:hover {
text-decoration: underline;
}
.fdz-upload {
margin-top: 14px;
padding: 10px 18px;
border-radius: 999px;
border: none;
background: linear-gradient(135deg, #4f46e5, #2563eb);
color: #ffffff;
font-weight: 600;
font-size: 0.95rem;
cursor: pointer;
}
.fdz-upload:disabled {
opacity: 0.7;
cursor: default;
}
.fdz-error {
margin-top: 8px;
font-size: 0.85rem;
color: #b91c1c;
}
When you run this application, on homepage it will show dropzone to allow user to upload files. Below is sample images of it.

Conclusion
Building a modern drag and drop file upload dropzone in React doesn’t have to be complicated. React-dropzone handles complex browser drag events for you, allowing you to create a clean, reusable component using a simple hook.
You now have a strong foundation for a drag-and-drop React file uploader that can handle backend uploads, multiple files, and removal. If necessary, you can then add previews, progress bars, file type filters, and validation. Treating file uploads as an essential component of the user experience makes your dropzone feel polished and natural, which facilitates onboarding and makes users happier.
