Frequently Asked Questions
Common questions and answers about Dropup.
General
What is Dropup?
Dropup is a lightweight, headless React library for file uploads. It provides drag-and-drop functionality, file validation, upload progress tracking, and support for cloud storage - all in a package under 10KB gzipped.
Why "headless"?
Headless means Dropup doesn't include any UI components. It provides the logic and state management, while you build the UI however you want. This gives you complete control over the look and feel.
What's the bundle size?
- Core (
@samithahansaka/dropup): < 10KB gzipped - With cloud support: +2KB per provider
- With image processing: +5KB
- With tus protocol: +3KB (requires tus-js-client peer)
Does it support TypeScript?
Yes! Dropup is written in TypeScript and includes comprehensive type definitions. No @types package needed.
What React version is required?
React 16.8+ (requires hooks support).
Usage
How do I upload files?
const { files, actions } = useDropup({
upload: { url: '/api/upload' },
});
// Upload all files
actions.upload();
// Upload specific files
actions.upload(['file-id-1', 'file-id-2']);
How do I handle validation errors?
useDropup({
accept: 'image/*',
maxSize: 5 * 1024 * 1024,
onValidationError: (errors) => {
errors.forEach(({ file, errors }) => {
console.log(`${file.name}: ${errors.join(', ')}`);
});
},
});
Can I use custom upload logic?
Yes! Pass a function instead of config object:
useDropup({
upload: async (file, options) => {
const { signal, onProgress } = options;
// Your custom upload logic
const response = await customUpload(file.file, {
signal,
onProgress,
});
return { url: response.url };
},
});
How do I add files programmatically?
const { actions } = useDropup();
// From clipboard
document.addEventListener('paste', (e) => {
const files = e.clipboardData?.files;
if (files) {
actions.addFiles(files);
}
});
Can I have multiple drop zones?
Yes! Each useDropup call creates an independent instance:
const images = useDropup({ accept: 'image/*' });
const documents = useDropup({ accept: '.pdf' });
// Use separately
<div {...images.getDropProps()}>...</div>
<div {...documents.getDropProps()}>...</div>
Uploads
How do I show upload progress?
const { files } = useDropup({ upload: { url: '/api/upload' } });
{files.map(file => (
<div key={file.id}>
{file.name}: {file.progress}%
</div>
))}
How do I cancel an upload?
const { actions } = useDropup();
// Cancel specific file
actions.cancel('file-id');
// Cancel all uploads
actions.cancel();
How do I retry failed uploads?
const { actions } = useDropup();
// Retry specific files
actions.retry(['file-id']);
// Retry all failed
actions.retry();
Does it support chunked uploads?
Yes! Use createChunkedUploader:
import { createChunkedUploader } from '@samithahansaka/dropup';
useDropup({
upload: createChunkedUploader({
url: '/api/upload/chunk',
chunkSize: 5 * 1024 * 1024, // 5MB
}),
});
Can I upload to S3 directly?
Yes! Use the cloud uploader:
import { createS3Uploader } from '@samithahansaka/dropup/cloud/s3';
useDropup({
upload: createS3Uploader({
getPresignedUrl: async (file) => {
const res = await fetch('/api/s3/presign', {
method: 'POST',
body: JSON.stringify({ filename: file.name }),
});
return res.json();
},
}),
});
Validation
How do I restrict file types?
// By MIME type
useDropup({ accept: 'image/*' });
// By extension
useDropup({ accept: '.pdf, .doc' });
// Multiple
useDropup({ accept: ['image/*', 'application/pdf'] });
How do I set size limits?
useDropup({
maxSize: 10 * 1024 * 1024, // 10MB max
minSize: 1024, // 1KB min
});
How do I limit number of files?
useDropup({
maxFiles: 5,
});
Can I add custom validation?
Yes! Use customRules:
useDropup({
customRules: [
(file) => {
if (file.name.includes('draft')) {
return 'Draft files not allowed';
}
return true;
},
],
});
Previews
How do I show image previews?
Previews are enabled by default:
const { files } = useDropup();
{files.map(file => (
file.preview && <img src={file.preview} alt="" />
))}
Do I need to clean up preview URLs?
No! Dropup automatically revokes Object URLs when files are removed or the component unmounts.
Can I disable previews?
useDropup({ generatePreviews: false });
Troubleshooting
Files aren't uploading
-
Check that
uploadis configured:useDropup({ upload: { url: '/api/upload' } }); -
Make sure you call
actions.upload()(unlessautoUpload: true) -
Check browser console for network errors
Preview URLs not working
- Ensure the file is an image
- Check that
generatePreviewsisn'tfalse - Verify the file object has a valid
previewproperty
Drag and drop not working
- Make sure you spread
getDropProps()on a container element - Include the hidden input:
<input {...getInputProps()} /> - Check that
disabledisn'ttrue
TypeScript errors
- Update to the latest Dropup version
- Ensure
tsconfig.jsonhas propermoduleResolution - Check that
@samithahansaka/dropupis independencies, notdevDependencies
Memory leaks
- Ensure components using
useDropupunmount properly - Call
actions.reset()before unmounting if needed - Don't store files in external state without cleanup
Compatibility
Does it work with Next.js?
Yes! Use the 'use client' directive:
'use client';
import { useDropup } from '@samithahansaka/dropup';
Does it work with React Native?
Yes! Use the native adapter:
import { NativeAdapter } from '@samithahansaka/dropup/native';
useDropup({ adapter: NativeAdapter });
Does it support SSR?
Yes! Dropup is SSR-safe. It only uses browser APIs when they're available.
Browser support?
All modern browsers:
- Chrome 60+
- Firefox 55+
- Safari 12+
- Edge 79+
Contributing
How can I contribute?
- Fork the repository
- Create a feature branch
- Submit a pull request
See CONTRIBUTING.md for details.
How do I report bugs?
Open an issue at github.com/samithahansaka/dropup/issues.
Is there a roadmap?
Check the GitHub issues and discussions for planned features.