Close Menu
Techs Slash

    Subscribe to Updates

    Get the latest creative news from FooBar about art, design and business.

    What's Hot

    React File Upload with Progress Tracking: A Step-by-Step Guide

    May 14, 2026

    Achieving Lasting Body Contouring Results in the Sonoran Desert

    May 13, 2026

    How AI Recommendation Engines Improve User Engagement in Property Listing Platforms

    May 13, 2026
    Facebook X (Twitter) Instagram
    Techs Slash
    • Home
    • News
      • Tech
      • Crypto News
      • Cryptocurrency
    • Entertainment
      • Actors
      • ANGEL NUMBER
      • Baby Names
      • Beauty
      • beauty-fashion
      • facebook Bio
      • Fitness
      • Dubai Tour
    • Business
      • Business Names
    • Review
      • Software
      • Smartphones & Apps
    • CONTRIBUTION
    Facebook X (Twitter) Instagram
    Techs Slash
    Home»Blog»React File Upload with Progress Tracking: A Step-by-Step Guide
    Blog

    React File Upload with Progress Tracking: A Step-by-Step Guide

    Milton MiltonBy Milton MiltonMay 14, 2026No Comments14 Mins Read
    Facebook Twitter Pinterest LinkedIn Tumblr Email
    Share
    Facebook Twitter LinkedIn Pinterest Email

    A simple file upload can feel broken without proper visual feedback. Users click upload, then nothing happens for several seconds, creating “silence” and doubt, especially for large files or slow connections. This is where React file upload progress tracking comes in.

    Progress feedback fixes that gap by showing users that the upload is working, how fast it moves, and when it will finish. This matters even more when handling large images, PDFs, or videos.

    Without proper progress tracking, users might retry uploads, refresh pages, or abandon the flow completely. Conversely, with it, they stay confident and in control. But how do you really start with it?

    The native <input type=”file”> element only lets users select files and not show progress. You must implement progress tracking yourself. In this article, you’ll explore different ways to do this in React and learn about some considerations for DIY implementations.

    Understanding the Progress Event

    To build React file upload progress tracking, you need access to low-level browser events. These are the more granular interactions between users and the browser, such as mouseup and mousedown (as opposed to click). The key concept is the ProgressEvent, which browsers emit during uploads.

    A ProgressEvent gives you three important values:

    • loaded: bytes uploaded so far
    • total: total bytes to upload
    • lengthComputable: whether the system can calculate progress

    From these, you can compute the percentage of progress:

    const percent = Math.round((event.loaded / event.total) * 100); 

    This event doesn’t come from React but from the browser’s networking layer. Instead, React simply listens and updates the UI state.

    Why XMLHttpRequest Still Matters

    Modern apps often use fetch, but React fetch upload progress is still limited. The Fetch API does not reliably expose upload progress in all browsers, making it unsuitable for consistent tracking. XMLHttpRequest solves this by exposing xhr.upload.onprogress, which fires continuously during uploads.

    Tip: Even if you use libraries like axios, they rely on this same underlying event.

    Part 1: Building the React Component with XMLHttpRequest

    Let’s build a working React file upload component example that supports real progress tracking.

    Step 1: Define Component State

    In this step, we need to track the following:

    • Selected file
    • Progress percentage
    • Upload status

    In your component (in this case, FileUploader.js), insert the following snippet:

    import React, { useState, useRef } from ‘react’;

    function FileUploader() {
      const [file, setFile] = useState(null);
      const [progress, setProgress] = useState(0);
      const [status, setStatus] = useState(‘idle’);

      const xhrRef = useRef(null);

      const handleFileChange = (e) => {
        setFile(e.target.files[0]);
        setProgress(0);
        setStatus(‘idle’);
      };

    This code sets up everything the component needs to track during upload.

    • file stores the selected file from the input
    • progress keeps the current upload percentage
    • status shows what’s happening (idle, uploading, success, error)
    • xhrRef keeps a reference to the active request so that we can cancel it later

    When a user selects a file, handleFileChange resets everything so a new upload starts cleanly.

    Step 2: Create the Upload Function

    Here is where React upload progress event handling happens. The handleUpload function manages the actual upload process:

    • A new XMLHttpRequest is created to send the file
    • FormData wraps the file so it can be sent like a normal form
    • xhr.upload.onprogress listens for upload updates and calculates the percentage
    • setProgress updates the UI in real time
    • onload checks if the upload succeeded
    • onerror handles network failures
    const handleUpload = () => {
        if (!file) return;

        const xhr = new XMLHttpRequest();
        xhrRef.current = xhr;

        const formData = new FormData();
        formData.append(‘file’, file);

        xhr.open(‘POST’, ‘http://localhost:5000/upload’);

        xhr.upload.onprogress = (event) => {
          if (event.lengthComputable) {
            const percent = Math.round((event.loaded / event.total) * 100);
            setProgress(percent);
            setStatus(‘uploading’);
          }
        };

        xhr.onload = () => {
          if (xhr.status === 200) {
            setStatus(‘success’);
          } else {
            setStatus(‘error’);
          }
        };

        xhr.onerror = () => {
          setStatus(‘error’);
        };

        xhr.send(formData);
      };

    Step 3: Add Cancel Support

    This function lets users stop an upload in progress. It works so that:

    • xhr.abort() immediately stops the request
    • The UI resets back to idle
    • Progress is cleared
    const handleCancel = () => {
        if (xhrRef.current) {
          xhrRef.current.abort();
          setStatus(‘idle’);
          setProgress(0);
        }
      };

    This improves UX, especially for large files or slow networks.

    Step 4: Render Basic UI

    This part connects everything to the screen.

    • The file input lets users choose a file.
    • The buttons trigger upload and cancel actions.
    • The progress bar reflects the current upload percentage.
    • Status text shows what’s happening.
    return (
        <div>
          <input type=”file” onChange={handleFileChange} />

          <div style={{ marginTop: ’10px’ }}>
            <button onClick={handleUpload}>Upload</button>
            <button onClick={handleCancel}>Cancel</button>
          </div>

          <div style={{ marginTop: ’10px’, width: ‘300px’, background: ‘#eee’ }}>
            <div
              style={{
                width: `${progress}%`,
                height: ’10px’,
                background: ‘blue’
              }}
            />
          </div>

          <p>Status: {status}</p>
          <p>{progress}%</p>
        </div>
      );

    Run the application, and you’ll see the application in action. Note that this simulation disables throttling in the network tab of the browser’s dev tools.

    At this stage, the app is fully functional. However, it might still feel a little lacking in terms of usability. Let’s fix that real quick.

    Part 2: Adding UI (Progress Bar, Cancel Button)

    At this point, the upload works. Now we improve how it feels for users. In this section, we’ll address the following concerns that users might have:

    • Is the upload slow or stuck?
    • Did something fail?
    • Should I retry?

    Better UI helps answer all these questions.

    Step 1: Improve the Progress Bar

    Replace your current bar with a clearer version:

    <div style={{ marginTop: ’10px’, width: ‘300px’ }}>
                    <div style={{ background: ‘#eee’, height: ’10px’, borderRadius: ‘5px’ }}>
                        <div
                        style={{
                        width: `${progress}%`,
                        height: ‘100%’,
                        background: progress === 100 ? ‘green’ : ‘blue’,
                        borderRadius: ‘5px’,
                        transition: ‘width 0.3s ease’
                        }}
                        />
                    </div>
                </div>

    This helps produce smoother animation and clearer feedback while also indicating visual completion (turns green at 100%).

    Step 2: Add Conditional Status Messages

    Replace your status text with:

    {status === ‘idle’ && <p>Select a file to upload</p>}
    {status === ‘uploading’ && <p>Uploading… {progress}%</p>}
    {status === ‘success’ && <p>Upload complete!</p>}
    {status === ‘error’ && <p>Upload failed. Try again.</p>}

    This lets users know what to do next and whether there are errors or not. Additionally, it makes the progress bar feel more active and not just static.

    Step 3: Disable Buttons When Needed

    Next, replace your original upload and cancel buttons with:

    <button onClick={handleUpload} disabled={!file || status === ‘uploading’}>
                        Upload
                    </button>

                    <button onClick={handleCancel} disabled={status !== ‘uploading’}>
                        Cancel
                    </button>

    This disables buttons as needed, preventing duplicate uploads and avoiding accidental clicks.

    Step 4: Show the File Name

    Lastly, let’s show the name of the file.

    {file && <p>File: {file.name}</p>}

    This confirms that the user selected the correct file, helping avoid user confusion or upload anxiety.

    Now, running the improved application should get you something like the GIF below. This upload simulation uses the “Fast 4G” preset of the browser network settings.

    Handling network failures, chunking, and cross-browser issues at the same time? Explore the React Filestack documentation to see a simple API-based implementation.

    Some Considerations for DIY Progress Tracking

    The implementation works because the browser exposes xhr.upload.onprogress. That gives you visibility into the uploaded bytes; however, this only covers a single uninterrupted request. The moment real-world conditions change, the model could break.

    Resumable Uploads

    Consider a user uploading a 200MB video on unstable Wi-Fi. If the connection drops at 95%, the current setup has no memory of progress. The upload then restarts from zero since the server treats it as a new request.

    This happens because the browser sends the file as one continuous stream; there is no checkpoint system. 

    To fix this, you need chunked uploads. This means splitting the file into smaller parts, sending each part separately, and tracking which chunks succeeded. You then reassemble the file on the server.

    This sounds manageable until you account for retries, ordering, and consistency. You now need to track chunk indexes, handle partial failures, and prevent duplicate chunks.

    Error Handling Complexity

    The normal progress tracking setup only treats failure as a simple success/error outcome based on xhr.status. In production, though, failures are rarely binary, and a request can succeed but return corrupted data. Moreover, a timeout may occur after the server has already processed part of the file. To handle this properly, you need:

    • Timeout awareness (client retries vs. server completion)
    • Idempotency (safe retries without duplication)
    • Validation after upload (file integrity checks like hashes)

    Without these, retries can create duplicate files, incomplete uploads, or inconsistent records in your database. This is typically where most implementations start breaking under real traffic.

    Browser Inconsistencies

    Even though XMLHttpRequest has wide support, behavior still varies across environments. For example, mobile browsers may throttle background uploads. Some browsers also delay or batch progress events, which makes your progress bar jump instead of update smoothly.

    Furthermore, large files expose memory limits differently depending on the device. On lower-end devices, uploads can silently fail or freeze the UI if there’s too much data buffering. To work around this, production systems

    • Throttle concurrency (limit simultaneous uploads)
    • Avoid loading entire files into memory
    • Normalize progress behavior in the UI

    State Management Overhead

    Tracking one file is straightforward, but the moment users upload multiple files, your state model needs to change. Each file now has its own progress, status, retry logic, and cancellation.

    In these scenarios, a single useState value may no longer work. You need a structured state (array or map) keyed by file ID, plus logic to update each upload independently. Avoiding designing this early on can lead to UI bugs appearing quickly, wrong progress bars updating, and canceled uploads continuing.

    Security and Validation

    File uploads are one of the most common entry points for untrusted input. The browser sends whatever the user selects, including files that may be disguised or intentionally crafted to exploit your system.

    Relying on file extensions or MIME types from the client is insufficient. This is because attackers can rename executable files to appear as images. Proper validation requires checking file signatures (magic bytes) on the server and rejecting anything that does not match expected formats.

    Beyond type validation, size limits are necessary to help prevent resource exhaustion or DDoS. Large uploads can consume memory, CPU, and storage, especially during processing steps like resizing or transformation.

    Storage also needs isolation. Uploaded files should not immediately appear accessible from public paths until the system validates and sanitizes them. Without this, an attacker could upload a malicious file and access it directly. To help protect your infrastructure from different kinds of attack.

    The Better Way: Implementing with Filestack

    The manual approach teaches you how upload progress works. It also exposes where the complexity actually resides, which includes handling unreliable networks, large files, and unpredictable user behavior.

    A managed solution like Filestack changes the model by moving those concerns into a dedicated service.

    Instead of sending one large request, Filestack automatically breaks files into chunks, and each chunk uploads independently and reports progress. If the network drops, only the failed chunks retry, resuming the upload instead of restarting. This addresses the problem you saw earlier with large files.

    Progress tracking also becomes more meaningful with managed solutions. In traditional setups, progress reflects a single request. With chunked uploads, progress reflects the aggregate state of multiple chunks. This produces smoother and more accurate feedback, especially for large files.

    Another improvement is consistency across browsers. Traditional React implementations rely on XMLHttpRequest, which behaves slightly differently depending on environment and file size. Filestack standardizes this behavior, so your app does not need browser-specific workarounds.

    Filestack also handles security at multiple layers, and files pass through validation, scanning, and controlled storage before becoming accessible. This removes the need to build your own validation pipeline while still allowing customization where needed.

    From a React perspective, integration becomes simpler. Instead of managing raw network requests, you work with a higher-level API that emits upload states. You still get progress updates, but without wiring low-level events yourself.

    This shifts your role from “implementing uploads” to “configuring upload behavior.” You decide limits, UI behavior, and integrations, while the service handles transport, retries, and scaling.

    For production applications, this matters because uploads tend to get more complex as time progresses. Requirements keep expanding to include better reliability, compliance, and performance. A managed approach reduces the surface area you need to maintain.

    Conclusion and Recommendation

    You now understand how to implement React file upload progress tracking, building a working solution using XMLHttpRequest and connecting it to a React state.

    That approach teaches the fundamentals, showing how browsers emit progress events and how UI reflects them. In turn, this knowledge helps you debug and extend most upload systems.

    However, production requirements can quickly grow beyond the basics of progress tracking. For example, large file handling, retry logic, and security introduce real complexity. At that point, the decision shifts from implementation to strategy, and you must decide where your team should spend its effort.

    If your project requires complete control over file upload handling, and if you have the time and resources, building custom solutions may make sense. If not, using a managed solution can significantly reduce long-term cost and risk.

    What you need to do then is to evaluate your use case. Identify expected file sizes, traffic, and reliability requirements. Afterwards, choose an approach that aligns best with your needs.

    Skip the complexity. Add robust file uploads with built-in progress tracking, resumable uploads, and a pre-built UI in minutes.

    Get Your API Key

    Share. Facebook Twitter Pinterest LinkedIn Tumblr Email
    Milton Milton

    Related Posts

    Achieving Lasting Body Contouring Results in the Sonoran Desert

    May 13, 2026

    How AI Recommendation Engines Improve User Engagement in Property Listing Platforms

    May 13, 2026

    Opener Repair: The Most Common Garage Door Opener Problems and What They Really Mean

    May 12, 2026
    Leave A Reply Cancel Reply

    Top Posts

    Sapne Me Nahane Ka Matlab

    March 18, 2024

    Sapne Me Nagn Stri Dekhna

    March 18, 2024

    Self Reliance: Release Date, Cast, Plot, Trailer, and More Information

    March 18, 2024

    Subscribe to Updates

    Get the latest creative news from FooBar about art, design and business.

    ABOUT TECHSSLASH

    Welcome to Techsslash! We're dedicated to providing you with the best of technology, finance, gaming, entertainment, lifestyle, health, and fitness news, all delivered with dependability.

    Our passion for tech and daily news drives us to create a booming online website where you can stay informed and entertained.

    Enjoy our content as much as we enjoy offering it to you

    Most Popular

    Sapne Me Nahane Ka Matlab

    March 18, 2024

    Sapne Me Nagn Stri Dekhna

    March 18, 2024

    Self Reliance: Release Date, Cast, Plot, Trailer, and More Information

    March 18, 2024
    CONTACT DETAILS

    Phone: +92-302-743-9438
    Email: contact@serpinsight.com

    Our Recommendation

    Here are some helpfull links for our user. hopefully you liked it.

    kakekmerah4d

    Techs Slash
    Facebook X (Twitter) Instagram Pinterest
    • Home
    • About us
    • contact us
    • Affiliate Disclosure
    • Privacy Policy
    • Disclaimer
    • Terms and Conditions
    • Write for us
    • Daman Game
    © 2026 Techsslash. All Rights Reserved

    Type above and press Enter to search. Press Esc to cancel.