How to Build a Custom Real-Time Image Upload Progress Bar in React and Tailwind

By Admin Updated June 6, 2026 27 Reads

How to Build a Custom Real-Time Image Upload Progress Bar in React and Tailwind

Introduction

Uploading images is something almost every modern web app needs—whether it’s social media, dashboards, or eCommerce platforms. But users don’t like waiting blindly while a file uploads. They want feedback, something visual, something real-time.

That’s exactly where a React image upload progress bar becomes important.

In this guide, you’ll learn how to build a real-time image upload system using React.js and Tailwind CSS that shows users exactly how much of their file has been uploaded. We’ll go step by step, from basic setup to advanced progress tracking using Axios and clean UI design.

We’re not just building a simple uploader. We’ll create a smooth experience where users can see upload percentage, progress animation, error handling, and success states—all in real time.

By the end, you’ll understand how to connect frontend state with upload events, how progress tracking works behind the scenes, and how to design a clean UI using Tailwind that feels modern and professional.

Let’s build something practical, real, and production-ready.


Understanding How Real-Time Upload Progress Works

What happens during file upload?

When you upload a file, your browser sends it to a server in small chunks. Instead of waiting for the full upload to finish, we can track how many bytes have been sent.

This is how real-time progress works.

To build a React image upload progress bar, we usually rely on tools like:

  • Axios (for HTTP requests)
  • XMLHttpRequest (native browser API)
  • Backend API (Node.js, PHP, etc.)

Axios is preferred because it provides a simple onUploadProgress event.

Why progress bars matter

Without a progress bar:

  • Users think the app is stuck
  • They may refresh the page
  • Upload gets interrupted

With a progress bar:

  • Users trust the system
  • UX feels professional
  • Conversion rates improve

Even simple apps feel premium when upload feedback is smooth.


Setting Up React + Tailwind Project

React image upload progress bar

Step 1: Create React app

Run:

npx create-react-app image-uploader
cd image-uploader
npm start

Step 2: Install Tailwind CSS

npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init -p

Configure tailwind.config.js:

content: ["./src/**/*.{js,jsx,ts,tsx}"],

Add Tailwind to index.css:

@tailwind base;
@tailwind components;
@tailwind utilities;

Step 3: Install Axios

npm install axios

Now we are ready to build the upload system.


Building the Image Upload Component

File structure

Create:

components/ImageUploader.js

We will manage:

  • File selection
  • Upload request
  • Progress tracking
  • UI updates

Basic UI layout

Here is a simple upload box:

export default function ImageUploader() {
  return (
    <div className="w-full max-w-md mx-auto mt-10 p-6 border rounded-xl shadow">
      <h2 className="text-xl font-semibold mb-4">
        Upload Your Image
      </h2>

      <input type="file" className="mb-4" />
    </div>
  );
}

This is our starting point.


Adding Real-Time Upload Logic

State management

We need React state:

import { useState } from "react";
import axios from "axios";

Then:

const [file, setFile] = useState(null);
const [progress, setProgress] = useState(0);
const [uploading, setUploading] = useState(false);
const [uploadedUrl, setUploadedUrl] = useState("");

Handling file selection

const handleFileChange = (e) => {
  setFile(e.target.files[0]);
};

Upload function with progress tracking

This is the core part of how to build real time upload progress bar react tailwind system.

const uploadImage = async () => {
  const formData = new FormData();
  formData.append("image", file);

  setUploading(true);

  try {
    const res = await axios.post(
      "https://your-api.com/upload",
      formData,
      {
        headers: {
          "Content-Type": "multipart/form-data",
        },
        onUploadProgress: (progressEvent) => {
          const percent = Math.round(
            (progressEvent.loaded * 100) /
            progressEvent.total
          );
          setProgress(percent);
        },
      }
    );

    setUploadedUrl(res.data.url);
  } catch (error) {
    console.log("Upload failed", error);
  }

  setUploading(false);
};

Creating the Progress Bar UI with Tailwind

Progress bar design

<div className="w-full bg-gray-200 rounded-full h-3 mt-4">
  <div
    className="bg-green-500 h-3 rounded-full transition-all duration-300"
    style={{ width: `${progress}%` }}
  ></div>
</div>

Percentage display

<p className="text-sm mt-2 text-gray-600">
  Uploading: {progress}%
</p>

This gives real-time feedback.


Full Working Component Example

import { useState } from "react";
import axios from "axios";

export default function ImageUploader() {
  const [file, setFile] = useState(null);
  const [progress, setProgress] = useState(0);
  const [uploading, setUploading] = useState(false);
  const [uploadedUrl, setUploadedUrl] = useState("");

  const handleFileChange = (e) => {
    setFile(e.target.files[0]);
  };

  const uploadImage = async () => {
    const formData = new FormData();
    formData.append("image", file);

    setUploading(true);

    try {
      const res = await axios.post(
        "https://your-api.com/upload",
        formData,
        {
          onUploadProgress: (progressEvent) => {
            const percent = Math.round(
              (progressEvent.loaded * 100) /
              progressEvent.total
            );
            setProgress(percent);
          },
        }
      );

      setUploadedUrl(res.data.url);
    } catch (err) {
      console.log(err);
    }

    setUploading(false);
  };

  return (
    <div className="max-w-md mx-auto mt-10 p-6 border rounded-xl shadow-lg">
      <h2 className="text-xl font-bold mb-4">
        Image Upload
      </h2>

      <input type="file" onChange={handleFileChange} />

      <button
        onClick={uploadImage}
        className="bg-blue-500 text-white px-4 py-2 rounded mt-4"
      >
        Upload
      </button>

      {uploading && (
        <>
          <div className="w-full bg-gray-200 rounded-full h-3 mt-4">
            <div
              className="bg-blue-500 h-3 rounded-full transition-all"
              style={{ width: `${progress}%` }}
            />
          </div>

          <p className="text-sm mt-2">{progress}% uploaded</p>
        </>
      )}

      {uploadedUrl && (
        <img
          src={uploadedUrl}
          alt="uploaded"
          className="mt-4 rounded"
        />
      )}
    </div>
  );
}

Pro Tips for Better Upload Experience

React image upload progress bar

Building a smooth React image upload progress bar is not just about code—it’s about UX.

Here are some practical tips:

  • Always disable upload button during upload
  • Show loading spinner with progress
  • Compress images before uploading
  • Limit file size (e.g. 2MB or 5MB)
  • Use drag & drop support
  • Show preview before upload
  • Add retry button for failed uploads

A small UI improvement can make your app feel like a premium product.


Common Mistakes to Avoid

Many beginners struggle while building upload systems.

Avoid these mistakes:

Not using onUploadProgress correctly

If you don’t attach it properly, progress will never update.

Forgetting FormData

Normal JSON cannot send files.

No error handling

If upload fails, user should know instantly.

Not validating files

Always check:

  • File type (jpg, png)
  • File size
  • Empty selection

Blocking UI during upload

Never freeze the screen—keep it interactive.


Advanced Level: Making It Production Ready

Once your basic uploader works, you can upgrade it into a real system.

1. Chunked Uploads

Large files should be split into chunks:

  • Upload in parts
  • Reassemble on server
  • Better reliability

2. Cloud Storage Integration

Instead of local server, use:

  • AWS S3
  • Cloudinary
  • Firebase Storage

3. Parallel Upload Queue

Allow multiple images upload at once.

4. Cancel Upload Feature

Using Axios cancel tokens:

  • Stop upload anytime
  • Improve user control

5. Animated Progress UI

Instead of static bar:

  • Add shimmer effect
  • Smooth transitions
  • Gradient progress fill

These upgrades turn a simple feature into a professional system used in real SaaS platforms.


FAQ Section

How does React track upload progress?

React itself doesn’t track upload progress directly. Instead, libraries like Axios use browser-level events such as onUploadProgress. These events report how many bytes have been uploaded so far. React simply updates the state based on this data and re-renders the UI to show a live progress bar.


Can I build upload progress without Axios?

Yes, you can use native XMLHttpRequest to track upload progress. It provides an upload.onprogress event. However, Axios simplifies the process and integrates better with React applications. For beginners, Axios is easier and more readable, while XHR offers more control for advanced developers.


How can I improve upload speed?

Upload speed depends on file size, network, and backend optimization. You can improve it by compressing images before upload, using CDN storage, enabling chunk uploads, and optimizing server response time. Reducing file resolution before sending also helps significantly.


Is Tailwind necessary for progress bars?

No, Tailwind is not required. You can use plain CSS or any UI framework. However, Tailwind makes styling faster and cleaner. It helps you build responsive and modern UI without writing long custom CSS files.


Can I upload multiple images with progress tracking?

Yes. You can loop through files and upload them individually or use parallel upload logic. Each file can have its own progress state. This requires managing an array of progress values instead of a single state.


Also Read 

How to Fix a "Mismatched Anonymous Defines" Error in Node.js Backend Modules

Leave a Comment

Your email address will not be published. Required fields are marked *

© 2026 Your Company. All rights reserved.
Home About Us Contact Us DMCA Privacy Policy