How to Build a Drag and Drop File Upload Feature in React - No Libraries Needed!
In this tutorial, we will walk through the process of building a drag-and-drop file upload in React, step by step, without using a library.
Create the Upload Component
Inside your src folder, create a new file and call it Upload.jsx, and add the following code inside:
import React, { useRef, useState } from "react"
export default function Upload() {
const [imageUrl, setImageUrl] = useState(null)
const inputRef = useRef(null)
// Trigger file input when dropzone is clicked
const handleClick = () => {
inputRef.current.click();
}
// Event handler for file drop
const handleDrop = (e) => {
e.preventDefault()
handleFile(e.dataTransfer.files[0])
}
// Event handler for file input change (for click to select)
const handleFileSelect = (e) => {
handleFile(e.target.files[0])
// This ensures that even if you choose the same
// file multiple times, the component will recognize the selection
// and proceed with the upload process.
e.target.value = ''
}
// Handle file drop / select
const handleFile = (file) => file && displayImage(file)
// Displays the image preview from a file object
const displayImage = (file) => {
const reader = new FileReader()
reader.onload = () => setImageUrl(reader.result)
reader.readAsDataURL(file)
}
return (
<div className="row my-4">
<div className="col-md-6 mx-auto">
<div className="card">
<div className="card-header text-center bg-white">
<h3 className="mt-2">Upload Your Image</h3>
</div>
<div className="card-body">
<form onSubmit={(e) => uploadImage(e)}>
<div
id="dropzone"
onDrop={handleDrop}
onDragOver={(e) => e.preventDefault()}
onDragLeave={(e) => e.preventDefault()}
onClick={handleClick}
className="rounded p-5 text-center"
>
<label htmlFor="file-input" className="form-label mb-2">
Drag & Drop Your Image Here or Click to Select
</label>
<input
type="file"
name="image"
id="file-input"
className="form-control"
accept="image/*"
onChange={handleFileSelect}
ref={inputRef}
hidden
/>
{
imageUrl && <img src={imageUrl} alt="Preview" className="img-fluid mt-3 rounded shadow-sm" style={{maxHeight: '200px'}} />
}
</div>
<button type="submit" className="btn btn-primary w-100 mt-3">
Upload Image
</button>
</form>
</div>
</div>
</div>
</div>
)
}
Add Some CSS Styles to the Upload Component
Inside the index.css file, let's add some CSS styles to our upload component.
/* dropzone */
#dropzone {
background: #f8f9fa;
border: 2px dashed #666;
cursor: pointer;
transition: background 0.3s, border-color 0.3s;
}
#dropzone label {
cursor: pointer;
}
#dropzone:hover {
background-color: #f0eeee;
border-color: #888;
}
Install & Use Bootstrap 5
Next, let's install Bootstrap 5 using the command:
npm install bootstrap@5.3.8
Now, inside your main.js file, we can import and use Bootstrap 5.
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import 'bootstrap/dist/css/bootstrap.min.css'
import './index.css'
import App from './App.jsx'
createRoot(document.getElementById('root')).render(
<StrictMode>
<App />
</StrictMode>,
)
Use It in Your App Component
Inside the App.jsx file, let's import and use the Upload Component.
import Upload from "./Upload"
function App() {
return (
<Upload />
)
}
export default App