Renderless components
Import from react-upload-kit/components. Each component is a hook plus a render prop — no DOM of its own besides what you return.
ts
import { Dropzone, FileList, UploadTrigger } from 'react-upload-kit/components';<Dropzone>
Wraps useDropzone. Props are DropzoneOptions plus children.
tsx
<Dropzone onDrop={uploader.addFiles} accept={['image/*']}>
{({ getRootProps, getInputProps, isDragActive, isDragReject, open }) => (
<div {...getRootProps()}>
<input {...getInputProps()} />
{isDragActive ? 'Drop here' : 'Drag & drop or click'}
</div>
)}
</Dropzone>children receives the full DropzoneState.
<FileList>
Maps files and, per item, runs useFilePreview for images.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
files | UploadFile<TResponse>[] | required | Uploader file list |
children | (ctx) => ReactNode | required | Per-file render |
onRemove | (id: string) => void | — | Wired to remove |
onRetry | (id: string) => void | — | Wired to retry |
onCancel | (id: string) => void | — | Wired to cancel |
previewEnabled | boolean | true | Generate image previews |
previewMaxWidth | number | — | Canvas max width |
previewMaxHeight | number | — | Canvas max height |
Child context
| Field | Type | Description |
|---|---|---|
file | UploadFile<TResponse> | Row state |
preview | string | null | Object URL for images |
isPreviewLoading | boolean | Resize in progress |
remove | () => void | Calls onRemove(file.id) |
retry | () => void | Calls onRetry(file.id) |
cancel | () => void | Calls onCancel(file.id) |
tsx
<FileList
files={uploader.files}
onRemove={uploader.removeFile}
onRetry={uploader.retryFile}
onCancel={uploader.cancelFile}
previewMaxWidth={96}
previewMaxHeight={96}
>
{({ file, preview, remove, retry, cancel }) => (
<div>
{preview && <img src={preview} alt={file.file.name} />}
<span>{file.file.name}</span>
<progress value={file.progress} max={100} />
<button type="button" onClick={remove}>Remove</button>
{file.status === 'error' && (
<button type="button" onClick={retry}>Retry</button>
)}
{file.status === 'uploading' && (
<button type="button" onClick={cancel}>Cancel</button>
)}
</div>
)}
</FileList>remove / retry / cancel are no-ops if the corresponding callback is omitted.
<UploadTrigger>
Hidden file input plus an open() helper. Use when you want a button outside the dropzone.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
onSelect | (files: File[]) => void | required | Selected files |
accept | string[] | — | Input accept |
multiple | boolean | true | Multi-select |
disabled | boolean | false | Blocks open and the input |
children | (ctx) => ReactNode | required | Must render the <input> |
Child context
| Field | Type | Description |
|---|---|---|
open | () => void | Opens the file dialog |
inputProps | Record<string, unknown> | Spread onto <input> |
tsx
<UploadTrigger onSelect={uploader.addFiles} accept={['image/*']}>
{({ open, inputProps }) => (
<>
<button type="button" onClick={open}>Select files</button>
<input {...inputProps} />
</>
)}
</UploadTrigger>UploadTrigger does not run validateFiles. Pass selections into uploader.addFiles so size/count/MIME rules still apply.
Guide: Components. Example: Declarative UI.