Skip to content

Components

Hooks are the primary API. The react-upload-kit/components entrypoint is a thin, renderless layer for teams that prefer JSX over prop-getters in the parent.

Nothing is styled. Each component calls a hook and passes state to children.

When to use them

Prefer hooksPrefer components
You already compose useUploader + useDropzone in one placeYou want dropzone / list / trigger as separate tree nodes
You need to share dropzone state with siblingsRender-prop children keep markup colocated
Bundle size of an extra import matters (it is small either way)You are wrapping them in your own design-system primitives

They are interchangeable. Dropzone is useDropzone. FileList maps files and wires useFilePreview per row. UploadTrigger is a hidden file input + open().

Typical composition

tsx
import { useUploader } from 'react-upload-kit';
import { Dropzone, FileList, UploadTrigger } from 'react-upload-kit/components';

function Uploader() {
  const uploader = useUploader({ adapter, accept: ['image/*'], autoUpload: true });

  return (
    <>
      <Dropzone onDrop={uploader.addFiles} accept={['image/*']}>
        {({ getRootProps, getInputProps, isDragActive }) => (
          <div {...getRootProps()}>
            <input {...getInputProps()} />
            {isDragActive ? 'Drop here' : 'Drop or click'}
          </div>
        )}
      </Dropzone>

      <UploadTrigger onSelect={uploader.addFiles} accept={['image/*']}>
        {({ open, inputProps }) => (
          <>
            <button type="button" onClick={open}>Browse</button>
            <input {...inputProps} />
          </>
        )}
      </UploadTrigger>

      <FileList
        files={uploader.files}
        onRemove={uploader.removeFile}
        onRetry={uploader.retryFile}
        onCancel={uploader.cancelFile}
      >
        {({ file, preview, remove, retry, cancel }) => (
          <div key={file.id}>
            {preview && <img src={preview} alt={file.file.name} />}
            <span>{file.file.name}</span>
            <button onClick={remove}>Remove</button>
            {file.status === 'error' && <button onClick={retry}>Retry</button>}
            {file.status === 'uploading' && <button onClick={cancel}>Cancel</button>}
          </div>
        )}
      </FileList>
    </>
  );
}

FileList still expects you to return a key on the root of each child (or wrap in an element that has one). The component uses file.id internally for the map, but the node you return should also be keyed if it is a list item.

Previews in FileList

FileList enables image previews by default (previewEnabled). Pass previewMaxWidth / previewMaxHeight to resize via canvas. Non-image files get preview: null.

If you already call useFilePreview yourself, set previewEnabled={false} and skip the extra object URLs.

Full prop tables: Renderless components. A complete example: Declarative UI.

Released under the MIT License.