npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

react-file-progress

v0.1.0

Published

React progress bar for reading a file from the hard disk/SSD into the browser, plus a separate one for uploading it to your server when you choose. Drop zone, swappable components, zero dependencies, TypeScript types

Readme

react-file-progress

React file upload component with two progress bars — one for reading the file from the user's hard disk or SSD into the browser, and a separate one for uploading it to your server. Drag and drop, TypeScript, zero dependencies.

NPM License

▶ Try the live demo

What is a "file loading" progress bar?

When someone picks a file, the browser does not have it yet. The file is still sitting on their hard drive or SSD, and it has to be read from that disk into the browser's memory before your JavaScript can touch it. For a big video or a large PDF that read takes real time, and until now users stared at a frozen screen while it happened.

This library shows a progress bar for that read — from the hard disk / SSD into the browser. No server, no network, no upload. Just "your file is being loaded, here's how far along it is".

The GIF above is slowed down on purpose so you can see the bar move. On a fast local SSD, reading a 150MB file into the browser takes only about 90 milliseconds — measured, not guessed. The bar earns its keep where that read is genuinely slow: network drives and SMB shares, cloud-synced folders like iCloud or Google Drive, external USB disks, SD cards, and phones. On a quick SSD it simply flashes past, which is the correct behaviour.

Sending that file to your server afterwards is a completely separate step that you trigger yourself — with its own, second progress bar.

  • Zero dependencies, no CSS import, TypeScript types, SSR safe
  • Works with no server at allurl is optional
  • Every part swappable: your own card, your own bar, or no UI at all

Install

npm install --save react-file-progress

React 16.8 or newer is required (it is a peer dependency).

The two stages

add file ──▶ loading ──▶ ready ──▶ uploading ──▶ uploaded
             automatic    file is    only when you call
                          in browser  upload()

A file always loads into the browser, with a progress bar. It then sits at ready — name shown, bytes available on item.data — until you upload it. Set uploadFileOnLoad if you'd rather that happen automatically.

In other words: stage one is disk → browser (reading the file off the hard drive), stage two is browser → server (the actual upload). Most libraries only show you the second one.

Usage

Just load files into the browser. No server involved:

import { FileUpload } from 'react-file-progress'

<FileUpload
  accept='image/*'
  maxSize={10 * 1024 * 1024}
  onLoadComplete={(item) => console.log(item.file.name, item.data)}
/>

Add a url and each ready file gets an Upload button:

<FileUpload url='/api/upload' onUploadComplete={(item) => console.log(item.response)} />

Or skip the wait and upload as soon as each file lands:

<FileUpload url='/api/upload' uploadFileOnLoad />

Props

| Prop | What it does | Default | | --- | --- | --- | | url | Where upload() sends files. Omit it to only load into the browser | — | | uploadFileOnLoad | Upload each file as soon as it finishes loading | false | | accept | Allowed file types, same as the input attribute: '.pdf,image/*' | all | | maxSize | Largest allowed file, in bytes | ∞ | | onLoadComplete | File is in the browser — item.data holds the bytes | — | | onUploadComplete | Server accepted it — item.response holds the reply | — | | onError | Loading, uploading or validation failed | — | | method headers fieldName | Request shape — auth tokens go in headers | POST · — · 'file' | | multiple disabled label hint | Drop zone basics | true · false | | progressBar | Props for every bar (see below) | — | | components classNames | Swap parts out, or just restyle them | — | | children | Render prop — your UI, this library's logic | — |

Rejected files appear in the same list as errors, so there's only one thing to render.

Customizing

The barprogressBar forwards to every bar:

<FileUpload url='/api/upload' progressBar={{ width: '100%', height: 10, color: '#8b5cf6', showLabel: true }} />

value status width height color trackColor radius showLabel formatLabel indeterminate. Numbers become px. It's exported standalone too: <ProgressBar value={62} showLabel />.

Whole components — override one, keep the rest:

<FileUpload components={{ Container: MyCard, ProgressBar: MyBar }} />

| Slot | Gets | | --- | --- | | Container | children, className, style | | DropZone | isDragging, disabled, label, hint, browse() | | Item | item, upload(), cancel(), retry(), remove(), canUpload | | ProgressBar | value, status, plus everything above |

CSS — class names are stable and unhashed (rfu-root, rfu-item, rfu-progress…), bars carry data-status, and colors are custom properties:

.rfu-root {
  --rfu-bar-color: #3b82f6;          /* uploading */
  --rfu-bar-color-loading: #a78bfa;  /* loading into the browser */
  --rfu-success: #22c55e;
  --rfu-danger: #ef4444;
  --rfu-surface: #fff;
  --rfu-text: #111;
  --rfu-radius: 12px;
}

The hook

Same logic, no UI:

const { items, addFiles, upload, cancel, retry, remove, clear, isBusy } =
  useFileUpload({ url: '/api/upload' })

Each item is { id, file, data, status, loadProgress, uploadProgress, error, response }, where status is loading | ready | uploading | uploaded | error and data is the loaded Blob. upload() sends every ready file; upload(id) sends one.

item.data is kept until you remove() the file, so previews and re-uploads never re-read from disk. Several large files therefore stay in memory — call remove() or clear() when you're done with them.

FAQ

How do I show a progress bar while a file loads into the browser in React? Render <FileUpload /> with no url. Every file added is read from disk with a live progress bar and ends up at ready, with its bytes on item.data. Nothing is sent anywhere.

How do I show upload progress without uploading immediately? That is the default here. The file loads into the browser and waits. Call upload() from your own button when you're ready, or set uploadFileOnLoad to send it automatically.

Why doesn't my upload progress bar work with fetch? fetch cannot report upload progress portably — streaming request bodies need duplex: 'half', which is Chromium-only and requires HTTP/2. This library uses XMLHttpRequest, whose upload.onprogress works everywhere.

How do I read a large file in the browser without freezing the UI? Blob.stream() reads it in chunks so the main thread stays responsive, and each chunk updates progress. This library does that for you and falls back to FileReader on older browsers.

How do I limit file type and size? accept='image/*,.pdf' and maxSize={10 * 1024 * 1024}. Rejected files appear in the same list with an error, so there's only one thing to render.

Does it work without the built-in UI? Yes — useFileUpload() gives you the same logic headless, or pass a children render prop to keep the logic and write your own markup.

Notes

Loading uses Blob.stream() where available (Chrome 76+, Firefox 102+, Safari 14.1+) and falls back to FileReader, which reports progress just as accurately. Uploads use XMLHttpRequest because fetch still can't report upload progress portably — streaming request bodies need duplex: 'half', which is Chromium-only and requires HTTP/2.

Development

npm install          # installs and builds
npm run verify       # generated-file check, lint, typecheck, tests, build
cd example && npm install && npm run dev

The example is the live demo, and npm run deploy publishes it to GitHub Pages. Running it locally is worth it: the dev server has a deliberately throttled upload endpoint built in, so the bars move at a watchable speed instead of finishing instantly.

Styles live in src/styles.css — the single source of truth. A script turns it into src/styles.ts (injected at runtime) and copies it to dist/index.css; both run automatically on build and test. Edit the .css, never the generated .ts. Tests drive a fake XMLHttpRequest, because jsdom won't fire upload.onprogress without a real network stack.

License

MIT © codeAesthetic