What is react-dropzone?
The react-dropzone npm package is a simple and highly customizable dropzone component for React applications. It allows users to drag and drop files into an area of a web page or click to select files through the file explorer. It is designed to provide developers with a flexible and easy-to-use interface for handling file uploads.
What are react-dropzone's main functionalities?
Basic File Drop
This feature allows users to create a basic dropzone area where files can be dragged and dropped or selected through a file dialog.
import React from 'react';
import { useDropzone } from 'react-dropzone';
function BasicDropzone() {
const { getRootProps, getInputProps } = useDropzone();
return (
<div {...getRootProps()}>
<input {...getInputProps()} />
<p>Drag 'n' drop some files here, or click to select files</p>
</div>
);
}
export default BasicDropzone;
Accepting Specific File Types
This feature allows developers to specify which file types the dropzone will accept, limiting the user to only select or drag those types.
import React from 'react';
import { useDropzone } from 'react-dropzone';
function SpecificTypeDropzone() {
const { getRootProps, getInputProps } = useDropzone({
accept: 'image/*'
});
return (
<div {...getRootProps()}>
<input {...getInputProps()} />
<p>Drag 'n' drop some images here, or click to select images</p>
</div>
);
}
export default SpecificTypeDropzone;
Styling Dropzone Based on Drag State
This feature allows developers to apply different styles to the dropzone depending on whether files are being dragged over it.
import React from 'react';
import { useDropzone } from 'react-dropzone';
function StyledDropzone() {
const { getRootProps, getInputProps, isDragActive } = useDropzone();
return (
<div {...getRootProps()} style={{
border: '2px dashed #eeeeee',
backgroundColor: isDragActive ? '#e0e0e0' : '#fafafa',
padding: '20px'
}}>
<input {...getInputProps()} />
{
isDragActive ?
<p>Drop the files here ...</p> :
<p>Drag 'n' drop some files here, or click to select files</p>
}
</div>
);
}
export default StyledDropzone;
Handling File Previews
This feature allows developers to handle file previews by creating image thumbnails for dropped files.
import React, { useState } from 'react';
import { useDropzone } from 'react-dropzone';
function FilePreviewDropzone() {
const [files, setFiles] = useState([]);
const { getRootProps, getInputProps } = useDropzone({
onDrop: acceptedFiles => {
setFiles(acceptedFiles.map(file => Object.assign(file, {
preview: URL.createObjectURL(file)
})));
}
});
const images = files.map(file => (
<div key={file.name}>
<img src={file.preview} style={{ width: '200px' }} alt='preview' />
</div>
));
return (
<section className='container'>
<div {...getRootProps()}>
<input {...getInputProps()} />
<p>Drag 'n' drop some files here, or click to select files</p>
</div>
<aside>
<h4>Files</h4>
{images}
</aside>
</section>
);
}
export default FilePreviewDropzone;
Other packages similar to react-dropzone
dropzone
Dropzone is a standalone JavaScript library that provides drag-and-drop file uploads with image previews. It's more feature-rich out of the box compared to react-dropzone, but it's not a React component by default, which means it might require additional integration effort in React applications.
react-dropzone-uploader
React Dropzone Uploader is a React component that provides a dropzone as well as file previews and upload status. It offers more built-in features for handling uploads compared to react-dropzone, but it might be less flexible if you need to heavily customize the upload behavior.
filepond
FilePond is a flexible and fun JavaScript file upload library that can be turned into a React component using react-filepond. It provides a rich set of features like image optimization, file validation, and multiple file handling. It's a more comprehensive solution compared to react-dropzone but may be heavier if you only need a simple dropzone.
react-dropzone
Simple HTML5-compliant drag'n'drop zone for files built with React.js.
Documentation and examples: https://react-dropzone.js.org
Source code: https://github.com/react-dropzone/react-dropzone/
Looking for maintainers: https://github.com/react-dropzone/react-dropzone/issues/479
Installation
Install it from npm and include it in your React build process (using Webpack, Browserify, etc).
npm install --save react-dropzone
or:
yarn add react-dropzone
Usage
import React from 'react'
import classNames from 'classnames'
import Dropzone from 'react-dropzone'
class MyDropzone extends React.Component {
onDrop = (acceptedFiles, rejectedFiles) => {
}
render() {
return (
<Dropzone onDrop={this.onDrop}>
{({getRootProps, getInputProps, isDragActive}) => {
return (
<div
{...getRootProps()}
className={classNames('dropzone', {'dropzone--isActive': isDragActive})}
>
<input {...getInputProps()} />
{
isDragActive ?
<p>Drop files here...</p> :
<p>Try dropping some files here, or click to select files to upload.</p>
}
</div>
)
}}
</Dropzone>
);
}
}
Render Prop Function
The render property function is what you use to render whatever you want to based on the state of Dropzone
:
<Dropzone>
{({getRootProps}) => <div {...getRootProps()} />}
</Dropzone>
Prop Getters
See https://react-dropzone.netlify.com/#proptypes {children}
for more info.
These functions are used to apply props to the elements that you render.
This gives you maximum flexibility to render what, when, and wherever you like. You call these on the element in question (for example: <div {...getRootProps()} />
).
You should pass all your props to that function rather than applying them on the element yourself to avoid your props being overridden (or overriding the props returned).
E.g.
<div
{...getRootProps({
onClick: evt => console.log(event)
})}
/>
State
See https://react-dropzone.netlify.com/#proptypes {children}
for more info.
Custom refKey
Both getRootProps
and getInputProps
accept custom refKey
(defaulted to ref
) as one of the attributes passed down in the parameter.
const StyledDropArea = styled.div`
// Some styling here
`
const Example = () => (
<Dropzone>
{({ getRootProps, getInputProps }) => (
<StyledDropArea {...getRootProps({ refKey: 'innerRef' })}>
<input {...getInputProps()} />
<p>Drop some files here</p>
</StyledDropArea>
)}
</Dropzone>
);
Warning: On most recent browsers versions, the files given by onDrop
won't have properties path
or fullPath
, see this SO question and this issue.
If you want to access file content you have to use the FileReader API.
onDrop: acceptedFiles => {
acceptedFiles.forEach(file => {
const reader = new FileReader();
reader.onload = () => {
const fileAsBinaryString = reader.result;
};
reader.onabort = () => console.log('file reading was aborted');
reader.onerror = () => console.log('file reading has failed');
reader.readAsBinaryString(file);
});
}
PropTypes
See https://react-dropzone.netlify.com/#proptypes
Testing
Important: react-dropzone
makes its drag'n'drop callbacks asynchronous to enable promise based getDataTransfer functions. In order to properly test this, you may want to utilize a helper function to run all promises like this:
const flushPromises = () => new Promise(resolve => setImmediate(resolve));
Example with enzyme 3:
it('tests drag state', async () => {
const flushPromises = () => new Promise(resolve => setImmediate(resolve));
const DummyChildComponent = () => null
const dropzone = mount(
<Dropzone>{props => <DummyChildComponent {...props} />}</Dropzone>
)
dropzone.simulate('dragEnter', {
dataTransfer: { files: files.concat(images) }
})
await flushPromises(dropzone)
dropzone.update()
const child = dropzone.find(DummyChildComponent)
expect(child).toHaveProp('isDragActive', true)
expect(child).toHaveProp('isDragAccept', false)
expect(child).toHaveProp('isDragReject', true)
})
Remember to update your mounted component before asserting any props. A complete example for this can be found in react-dropzone
s own test suite.
Support
Backers
Support us with a monthly donation and help us continue our activities. [Become a backer]
Become a sponsor and get your logo on our README on Github with a link to your site. [Become a sponsor]
License
MIT