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?)
| Option | Type | Default | Description |
|---|---|---|---|
maxFiles | number | Infinity | Max files (multiple mode only). |
maxSize | number | Infinity | Max size per file, in bytes. |
accept | string | '*' | Accepted types, e.g. image/* or .png,.jpg. |
multiple | boolean | false | Allow selecting more than one file. |
initialFiles | FileMetadata[] | [] | Pre-populated files (e.g. already-uploaded assets). |
onFilesChange | (files: FileWithPreview[]) => void | — | Called whenever the file list changes. |
onFilesAdded | (added: FileWithPreview[]) => void | — | Called 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.
Related
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.