Skip to content

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

PropTypeDefaultDescription
filesUploadFile<TResponse>[]requiredUploader file list
children(ctx) => ReactNoderequiredPer-file render
onRemove(id: string) => voidWired to remove
onRetry(id: string) => voidWired to retry
onCancel(id: string) => voidWired to cancel
previewEnabledbooleantrueGenerate image previews
previewMaxWidthnumberCanvas max width
previewMaxHeightnumberCanvas max height

Child context

FieldTypeDescription
fileUploadFile<TResponse>Row state
previewstring | nullObject URL for images
isPreviewLoadingbooleanResize in progress
remove() => voidCalls onRemove(file.id)
retry() => voidCalls onRetry(file.id)
cancel() => voidCalls 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

PropTypeDefaultDescription
onSelect(files: File[]) => voidrequiredSelected files
acceptstring[]Input accept
multiplebooleantrueMulti-select
disabledbooleanfalseBlocks open and the input
children(ctx) => ReactNoderequiredMust render the <input>

Child context

FieldTypeDescription
open() => voidOpens the file dialog
inputPropsRecord<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.

Released under the MIT License.