React Upload Component
rc-upload is a lightweight, unstyled React UI component for handling file uploads. It provides foundational upload capabilities such as drag-and-drop, folder uploads, and paste-from-clipboard functionality without imposing any specific visual design, allowing developers full control over the user interface. The current stable version is 4.11.0. The project maintains an active release cadence, with minor versions released periodically to introduce new features, address bugs, and update dependencies. Its key differentiators include its headless architecture, extensive customization options via props like `customRequest` and `beforeUpload`, and support for modern browser-based upload features. It is a core utility often used as a building block for more complex upload components.
Common errors
-
Error: 'Upload' is not exported from 'rc-upload'
cause Attempting to import `Upload` as a named export when it is exported as a default export.fixChange the import statement to `import Upload from 'rc-upload';` -
Type 'boolean' is not assignable to type 'string | ((file: File) => string | Promise<string>)'
cause Providing an incorrect type for the `action` prop, which expects a URL string or a function that returns a URL.fixEnsure the `action` prop is either a `string` (e.g., `action="/upload-target"`) or a function returning a `string` or `Promise<string>` (e.g., `action={(file) => `/api/upload/${file.name}`}`). -
Property 'directory' does not exist on type 'UploadProps'. Did you mean 'folder'?
cause Using the deprecated `directory` prop (removed since v4.10.0) instead of the `folder` prop.fixReplace `directory={true}` with `folder={true}` to enable folder uploads.
Warnings
- breaking The `directory` prop was deprecated in `v4.10.0` in favor of the `folder` prop for uploading entire directories. While `directory` might still function, it is not recommended and could be removed in future major versions.
- gotcha `rc-upload` is a headless component and does not provide any default UI or styling. Developers must implement their own visual presentation and interaction around the `Upload` component.
- gotcha While the README historically showed CommonJS `require('rc-upload')` for usage, modern React applications primarily use ES module `import` syntax. Using `require` in an ESM-only environment or attempting named imports when only a default export exists will lead to errors.
- breaking The type annotations for the `beforeUpload` function were updated in `v4.11.0`. While this is primarily a TypeScript-related change and not a functional one, projects with strict TypeScript configurations or custom `beforeUpload` implementations might encounter type errors after upgrading.
- gotcha `rc-upload` is distinct from `@rc-component/upload`. Although the GitHub repository `react-component/upload` shows commits related to both, `@rc-component/upload` is a separate package (currently at v1.x) and not a direct replacement or rename of `rc-upload` (v4.x). Ensure you are installing and importing from the correct package, `rc-upload`.
Install
-
npm install rc-upload -
yarn add rc-upload -
pnpm add rc-upload
Imports
- Upload
import { Upload } from 'rc-upload';import Upload from 'rc-upload';
- UploadProps
import { UploadProps } from 'rc-upload';import type { UploadProps } from 'rc-upload'; - RcFile
import type { RcFile } from 'rc-upload';
Quickstart
import React, { useState } from 'react';
import Upload from 'rc-upload';
import type { UploadProps, RcFile } from 'rc-upload';
const App: React.FC = () => {
const [fileList, setFileList] = useState<RcFile[]>([]);
const handleStart: UploadProps['onStart'] = (file) => {
console.log('onStart', file.name);
setFileList((prev) => [...prev, { ...file, status: 'uploading' }]);
};
const handleSuccess: UploadProps['onSuccess'] = (response, file) => {
console.log('onSuccess', response, file.name);
setFileList((prev) => prev.map(f => f.uid === file.uid ? { ...f, status: 'done' } : f));
};
const handleError: UploadProps['onError'] = (err, response, file) => {
console.error('onError', err, response, file.name);
setFileList((prev) => prev.map(f => f.uid === file.uid ? { ...f, status: 'error' } : f));
};
const handleProgress: UploadProps['onProgress'] = (event, file) => {
console.log('onProgress', Math.round(event.percent || 0) + '%', file.name);
};
const beforeUpload: UploadProps['beforeUpload'] = (file, currentFileList) => {
const isLt2M = file.size / 1024 / 1024 < 2;
if (!isLt2M) {
alert('File must be smaller than 2MB!');
return false; // Stop upload
}
console.log('beforeUpload', file.name, currentFileList.length);
return true; // Proceed with upload
};
return (
<div>
<h1>File Upload Demo</h1>
<Upload
action="https://www.mocky.io/v2/5cc8019d300000980a055e76" // Mock API endpoint
method="POST"
name="myFile"
multiple={true}
onStart={handleStart}
onSuccess={handleSuccess}
onError={handleError}
onProgress={handleProgress}
beforeUpload={beforeUpload}
withCredentials={false} // Adjust as needed for your backend
style={{
padding: '20px',
border: '2px dashed #ccc',
textAlign: 'center',
cursor: 'pointer',
margin: '20px 0'
}}
>
<button type="button">Click to Upload or Drag File Here</button>
</Upload>
{fileList.length > 0 && (
<div>
<h2>Upload Status:</h2>
<ul>
{fileList.map((file) => (
<li key={file.uid}>
{file.name} - {file.status} {file.status === 'uploading' && '(in progress)'}
</li>
))}
</ul>
</div>
)}
</div>
);
};
export default App;