Drag and Drop File Upload in React & Laravel — Step-by-Step Tutorial Part 2

2 months ago admin Laravel

In the second part of this tutorial, we will move to the frontend. First, we will create the upload component, and next, we will upload the file to our backend and save it in our database.


Install the Packages

First, let's install the packages we need. We will install Bootstrap 5 and axios using the command:

npm i axios bootstrap@5.3.8

Now, let's move to the main.js file and 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>,
)


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"
import axios from 'axios'

export default function Upload() {
    const [imageUrl, setImageUrl] = useState(null)
    const [file, setFile] = 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)
        setFile(file)
    }

     // Upload image
    const uploadImage = async (e) => {
        e.preventDefault()
        // Set the form data 
        const formData = new FormData()
        formData.append('file', file)
        
        // Send the request
        try {
            const response = await axios.post('http://127.0.0.1:8001/api/upload', formData)
            console.log(response.data)
        } catch (error) {
            console.error(error)
        }
    }


    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"
                                onClick={(e) => uploadImage(e)}
                                disabled={!file}
                            >
                                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;
}

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

Related Tuorials

Drag and Drop File Upload in React & Laravel — Step-by-Step Tutorial Part 1

In this tutorial, we will create a drag-and-drop file uploader using React 19 and Laravel 12. The us...


How to Add Query Parameters to Laravel Pagination

In this lesson, we will see how to add query parameters to Laravel pagination.Our goal in this lesso...


How to Add Query Parameters to Laravel Pagination with Vue 3 and Inertia.js

In this lesson, we will see how to add query parameters to Laravel pagination with Vue 3 and inertia...


How to Build a Shopping Cart in Laravel 12 (Step-by-Step) Part 3

In the third part of this tutorial, we will display the products on the home page and add, update, a...


How to Build a Shopping Cart in Laravel 12 (Step-by-Step) Part 2

In the second part of this tutorial, we will add the controllers we need with the function...


How to Build a Shopping Cart in Laravel 12 (Step-by-Step) Part 1

In this tutorial, we will Learn how to create a fully functional shopping cart in Laravel 12. The us...


How to Add a Relationship to a Select in Filament

In this lesson, we will see how to add a relationship to a select in Filament.Let's assume that we h...


How to Generate Slugs from a Title in Filament

In this lesson, we will see how to generate slugs from a title in Filament, Sometimes we need to gen...


How to Change the Order of the Filament Left Navigation Menu Items

In this lesson, we will see how to change the order of the filament left navigation menu items.Somet...


How to Hide the Info Widget on the Filament Dashboard

In this lesson, we will see how to hide the info widget on the Filament dashboard. The info widget i...