dimah-s3v1.5.5

useUpload

Headless React hook for single and multi-file S3 uploads with progress and retries.

useUpload manages the complete client-side upload lifecycle: file selection, validation against server constraints, presigned URL acquisition, chunked progress tracking, and final server confirmation.

components/avatar-uploader.tsx
"use client";

import { useUpload } from "@dimah-s3/react";

export function AvatarUploader() {
  const upload = useUpload({
    route: "avatar",
    onSuccess: (results) => {
      console.log("Uploaded object key:", results[0]?.key);
    },
  });

  return (
    <div
      {...upload.getRootProps()}
      className="border border-dashed p-6 rounded-lg text-center cursor-pointer hover:border-primary transition-colors"
    >
      <input {...upload.getInputProps()} />
      {upload.isUploading ? (
        <p className="text-sm font-medium">
          Uploading: {upload.progress.percent}%
        </p>
      ) : (
        <p className="text-sm text-muted-foreground">
          Click or drop avatar here
        </p>
      )}
    </div>
  );
}

File selection and intake

useUpload provides native bindings for drag-and-drop surfaces and file input elements:

  • getRootProps(): Spread onto your container element to bind drag-and-drop and click-to-browse handlers.
  • getInputProps(): Spread onto a hidden <input type="file" />.
  • open(): Programmatically trigger the OS file dialog from a custom button.
  • handleFiles(files): Manually submit File, File[], or FileList (e.g. from clipboard paste, webcam capture, or canvas blob).
const upload = useUpload({
  route: "avatar",
  noClick: true, // Prevents container click from opening file picker
});

return (
  <div {...upload.getRootProps()}>
    <input {...upload.getInputProps()} />
    <button type="button" onClick={() => upload.open()}>
      Choose File
    </button>
  </div>
);

Multi-file batch uploads

Set maxFiles to allow multiple file selections. You can control concurrency with concurrentFiles:

const upload = useUpload({
  route: "avatar",
  maxFiles: 5,
  concurrentFiles: 2,
  onFileSuccess: (file, result) => {
    console.log(`Uploaded ${file.name} to ${result.key}`);
  },
  onSuccess: (results) => {
    console.log("All uploads completed:", results);
  },
});

Progress and state tracking

The hook surfaces detailed reactive state for UI rendering:

  • phase: Current upload phase (idle | validating | presigning | uploading | finalizing | success | error).
  • progress: Aggregate progress object containing loaded, total, percent, and instantaneous speed (bytes/sec).
  • files: Per-file state array containing individual progress, status (pending, uploading, success, error), and previewUrl.
  • file: Convenience shorthand for files[0] when maxFiles is 1.
  • isUploading: Boolean flag indicating active byte transfer (phase === "uploading").
  • isPending: Boolean flag indicating in-flight operation from presign to confirmation.

Type reference

import type {
  UseUploadOptions,
  UseUploadReturn,
  UploadProgress,
  UploadResult,
  UploadFileState,
} from "@dimah-s3/react";

UseUploadOptions

Prop

Type


UseUploadReturn

Prop

Type

Frequently asked questions

On this page