Redpanda UIRedpanda UI
Hooks

useFileUpload

Headless state and handlers for file selection via click or drag-and-drop, with validation and previews.

Installation

useFileUpload is the headless engine behind the Dropzone component. It manages selected files, drag state, and validation errors, and hands back a set of event handlers you spread onto your own markup — so you control the UI while the hook handles size/type validation, single vs. multiple modes, object-URL previews (and their cleanup), and duplicate detection.

Usage

import { useFileUpload } from "@/hooks/use-file-upload";
import { Button } from "@/components/redpanda-ui/button";

function Uploader() {
  const [{ files, isDragging, errors }, actions] = useFileUpload({
    accept: "image/*",
    maxSize: 5 * 1024 * 1024,
    multiple: true,
    maxFiles: 5,
  });

  return (
    <div
      onDragEnter={actions.handleDragEnter}
      onDragLeave={actions.handleDragLeave}
      onDragOver={actions.handleDragOver}
      onDrop={actions.handleDrop}
      data-dragging={isDragging}
    >
      <input {...actions.getInputProps()} className="sr-only" />
      <Button onClick={actions.openFileDialog}>Choose files</Button>

      {files.map(({ id, file, preview }) => (
        <div key={id}>
          {preview ? <img src={preview} alt={file.name} /> : null}
          <span>{file.name}</span>
          <button type="button" onClick={() => actions.removeFile(id)}>
            Remove
          </button>
        </div>
      ))}

      {errors.map((error) => (
        <p key={error} className="text-destructive">{error}</p>
      ))}
    </div>
  );
}

API

useFileUpload(options?)

OptionTypeDefaultDescription
maxFilesnumberInfinityMax files (multiple mode only).
maxSizenumberInfinityMax size per file, in bytes.
acceptstring'*'Accepted types, e.g. image/* or .png,.jpg.
multiplebooleanfalseAllow selecting more than one file.
initialFilesFileMetadata[][]Pre-populated files (e.g. already-uploaded assets).
onFilesChange(files: FileWithPreview[]) => voidCalled whenever the file list changes.
onFilesAdded(added: FileWithPreview[]) => voidCalled with only the newly added files.

Returns [state, actions]

  • state: { files, isDragging, errors }
  • actions: { addFiles, removeFile, clearFiles, clearErrors, handleDragEnter, handleDragLeave, handleDragOver, handleDrop, handleFileChange, openFileDialog, getInputProps }

The package also exports a formatBytes(bytes, decimals?) helper for rendering file sizes.

For a ready-made UI, use the Dropzone component, which is built on this hook.

Built by malinskibeniamin. The source code is available on GitHub.

On this page