How to Add Drag-and-Drop Image Upload with Dropzone in React Using Tailwind CSS

In this tutorial, we’ll see how to add drag and drop image file upload with preview in React with Tailwind CSS and Dropzone. Before you begin, ensure your project has React, TypeScript, and Tailwind CSS installed and configured.

Install & Setup Tailwind CSS + React + Typescript + Vite

Run below command to install dropzone in react project.

npm install --save react-dropzone
# or:
yarn add react-dropzone

Build an easy drag-and-drop system for uploading images with a preview using the React Dropzone library. Make it happen using React’s useCallback and useState hooks, and style it up with Tailwind CSS.

import { useCallback, useState } from 'react';
import { useDropzone } from 'react-dropzone';

const ImageUpload = () => {
  const [selectedImage, setSelectedImage] = useState(null);

  const onDrop = useCallback(acceptedFiles => {
    const image = acceptedFiles[0];
    const reader = new FileReader();
    reader.onload = () => {
      setSelectedImage(reader.result);
    };
    reader.readAsDataURL(image);
  }, []);

  const { acceptedFiles, getRootProps, getInputProps } = useDropzone({
    onDrop,
    accept: {
      'image/*': []
    },
    multiple: false,
  });

  console.log('Accepted Files:', acceptedFiles);

  return (
    <div className="flex items-center justify-center h-screen">
      <div className="bg-white p-8 rounded-lg shadow-md">
        <div {...getRootProps()} className="dropzone text-center border-dashed border-2 border-gray-300 p-6 rounded-md">
          <input {...getInputProps()} />
          <p className="text-gray-600">Drag 'n' drop an image here, or click to select one</p>
        </div>
        {selectedImage && (
          <div className="mt-4">
            <h2 className="text-xl font-semibold mb-2">Selected Image</h2>
            <img src={selectedImage} alt="Selected" className="max-w-full rounded-md" />
          </div>
        )}
      </div>
    </div>
  );
};

export default ImageUpload;
react tailwind dropzone

Create a quick drag-and-drop image uploader with preview using React, TypeScript, and the React Dropzone library. Style it with Tailwind CSS for a polished look.

import { useCallback, useState, FC } from 'react';
import { useDropzone, DropzoneRootProps, DropzoneInputProps, DropzoneState } from 'react-dropzone';

interface ImageUploadProps {
  // Add any additional props here
}

const ImageUpload: FC<ImageUploadProps> = () => {
  const [selectedImage, setSelectedImage] = useState<string | null>(null);

  const onDrop = useCallback((acceptedFiles: File[]) => {
    const image = acceptedFiles[0];
    const reader = new FileReader();
    reader.onload = () => {
      setSelectedImage(reader.result as string);
    };
    reader.readAsDataURL(image);
  }, []);

  const {
    acceptedFiles,
    getRootProps,
    getInputProps,
  }: {
    acceptedFiles: File[];
  } & DropzoneRootProps & DropzoneInputProps & DropzoneState = useDropzone({
    onDrop,
    accept: {
      'image/*': []
    },
    multiple: false,
  });

  console.log('Accepted Files:', acceptedFiles);

  return (
    <div className="flex items-center justify-center h-screen">
      <div className="bg-white p-8 rounded-lg shadow-md">
        <div {...getRootProps()} className="dropzone text-center border-dashed border-2 border-gray-300 p-6 rounded-md">
          <input {...getInputProps()} />
          <p className="text-gray-600">Drag 'n' drop an image here, or click to select one</p>
        </div>
        {selectedImage && (
          <div className="mt-4">
            <h2 className="text-xl font-semibold mb-2">Selected Image</h2>
            <img src={selectedImage} alt="Selected" className="max-w-full rounded-md" />
          </div>
        )}
      </div>
    </div>
  );
};

export default ImageUpload;
 drop and drop with preview

Build a quick drag-and-drop image uploader with multiple file support and live previews using React, TypeScript, and Tailwind CSS.

import { useCallback, useState, FC } from 'react';
import { useDropzone, DropzoneRootProps, DropzoneInputProps, DropzoneState } from 'react-dropzone';

interface ImageUploadProps {
  // Add any additional props here
}

const ImageUpload: FC<ImageUploadProps> = () => {
  const [selectedImages, setSelectedImages] = useState<string[]>([]);

  const onDrop = useCallback((acceptedFiles: File[]) => {
    // Do something with the uploaded images, for example, display them.
    const imagePromises: Promise<string>[] = acceptedFiles.map((image) => {
      return new Promise((resolve) => {
        const reader = new FileReader();
        reader.onload = () => {
          resolve(reader.result as string);
        };
        reader.readAsDataURL(image);
      });
    });

    Promise.all(imagePromises).then((results) => {
      setSelectedImages(results);
    });
  }, []);

  const {
    acceptedFiles,
    getRootProps,
    getInputProps,
  }: {
    acceptedFiles: File[];
  } & DropzoneRootProps & DropzoneInputProps & DropzoneState = useDropzone({
    onDrop,
    accept: {
      'image/*': []
    },
    multiple: true,

  });


  console.log('Accepted Files:', acceptedFiles);

  return (
    <div className="flex items-center justify-center h-screen">
      <div className="bg-white p-8 rounded-lg shadow-md">
        <div {...getRootProps()} className="dropzone text-center border-dashed border-2 border-gray-300 p-6 rounded-md">
          <input {...getInputProps()} />
          <p className="text-gray-600">Drag 'n' drop images here, or click to select</p>
        </div>
        {selectedImages.length > 0 && (
          <div className="mt-4">
            <h2 className="text-xl font-semibold mb-2">Selected Images</h2>
            <div className="flex flex-wrap">
              {selectedImages.map((image, index) => (
                <img key={index} src={image} alt={`Selected ${index + 1}`} className="max-w-full rounded-md m-2" />
              ))}
            </div>
          </div>
        )}
      </div>
    </div>
  );
};

export default ImageUpload;
drop and drop with multiple image

Sources

See Also

React with Tailwind CSS File Upload Example

How to add Tailwind CSS Carousel React

How to Use DataTables in React with Tailwind CSS

React Tailwind CSS Forgot Password Example

React TypeScript Tailwind CSS Popup Modal Tutorial

React with Tailwind CSS Skeleton Loader Example

How Use Headless UI in React + Typescript + Tailwind

Create a Responsive Navbar React Tailwind CSS TypeScript

How to Use Toastify in React with Tailwind CSS

Aaronn
Aaronn

Hey there! I'm Aaronn, a Full Stack Developer who's all about React, NEXTJS, Node.js, and Tailwind CSS. I'm on a mission to craft awesome websites that look great and work even better.