react-dropzone
is an HTML5-compliant React component for handling the dragging and dropping of files.
HTML5 supports file uploads with <input type="file" />
. react-dropzone
provides you with additional functionality like customizing the dropzone, displaying a preview, and restricting file types and amounts.
Note: If you are working with Vue instead of React, consult our tutorial for vue-dropzone
.
In this tutorial, you will learn about adding react-dropzone
to your React projects and explore some of the functionality it provides.
To complete this tutorial, you’ll need:
This tutorial was verified with Node v15.3.0, npm
v7.4.0, react
v17.0.1, and react-dropzone
v11.2.4.
Start with using create-react-app
to generate a React App and then install dependecies:
- npx create-react-app react-dropzone-example
Change into the new project directory:
- cd react-dropzone-example
Install react-dropzone
:
- npm install react-dropzone@11.2.4
At this point, you have a new React project with react-dropzone
.
react-dropzone
has default settings that allow you to add it with minimal configuration.
At a minimum, you will need an onDrop
property that will handle the dropped files and some call-to-action text to help limit any user confusion:
import React, { useCallback } from 'react';
import { useDropzone } from 'react-dropzone';
function DropzoneComponent() {
const onDrop = useCallback(acceptedFiles => {
console.log(acceptedFiles);
}, []);
const {
getRootProps,
getInputProps
} = useDropzone({
onDrop
});
return (
<div {...getRootProps()}>
<input {...getInputProps()} />
<div>Drag and drop your images here.</div>
</div>
)
}
export default DropzoneComponent;
This code provides drag and drop functionality for your application.
Note: It is worth noting that even though react-dropzone
is designed to drag and drop files, it does accept click events to the dropzone by default which will launch a dialog for file selection.
Add the component to your React application:
import DropzoneComponent from './DropzoneComponent';
function App() {
return (
<div className="App">
<DropzoneComponent />
</div>
);
}
export default App;
Run your application and observe it in a web browser. You should see a div with the text: Drag and drop your images here
.
Experiment with dragging and dropping various files to the React Dropzone component. The code currently uses a console.log
to display the files. The information from uploaded files includes name
, lastModified
, size
, and type
.
At this point, you have a working React Dropzone component with the default configuration. The react-dropzone
documentation additional configuration options.
By default, the react-dropzone
will have no styles. The documentation provides styles for a common appearance that uses a combination of flexbox and dashed borders to indicate to users an area to drag and drop files.
react-dropzone
also supports props for when the component is actively interacted with (isDragActive
), accepted the file (isDragAccept
), or rejected the file (isDragReject
).
Revisit your DropzoneComponent
and modify it to use isDragActive
, isDragAccept
, and isDragReject
when applied to JPEG and PNG image file types:
import React, { useCallback, useMemo } from 'react';
import { useDropzone } from 'react-dropzone';
const baseStyle = {
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
padding: '20px',
borderWidth: 2,
borderRadius: 2,
borderColor: '#eeeeee',
borderStyle: 'dashed',
backgroundColor: '#fafafa',
color: '#bdbdbd',
transition: 'border .3s ease-in-out'
};
const activeStyle = {
borderColor: '#2196f3'
};
const acceptStyle = {
borderColor: '#00e676'
};
const rejectStyle = {
borderColor: '#ff1744'
};
function DropzoneComponent(props) {
const onDrop = useCallback(acceptedFiles => {
console.log(acceptedFiles);
}, []);
const {
getRootProps,
getInputProps,
isDragActive,
isDragAccept,
isDragReject
} = useDropzone({
onDrop,
accept: 'image/jpeg, image/png'
});
const style = useMemo(() => ({
...baseStyle,
...(isDragActive ? activeStyle : {}),
...(isDragAccept ? acceptStyle : {}),
...(isDragReject ? rejectStyle : {})
}), [
isDragActive,
isDragReject,
isDragAccept
]);
return (
<div {...getRootProps({style})}>
<input {...getInputProps()} />
<div>Drag and drop your images here.</div>
</div>
)
}
export default DropzoneComponent;
This code will produce the following result:
Changing the appearance of the component for acceptions and rejections can help provide feedback to the user on whether or not their file is valid.
A preview is a copy of the image that is dragged and dropped in the component. This is helpful to provide visual feedback to the user to verify the contents of the image file they selected.
Previews were removed in version 7.0.0, however, the documentation provides an alternative for readding it with a combination of Object.assign()
and URL.createObjectURL()
.
Revisit your DropzoneComponent
and modify it to use preview
:
import React, { useCallback, useEffect, useMemo, useState } from 'react';
import { useDropzone } from 'react-dropzone';
const baseStyle = {
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
padding: '20px',
borderWidth: 2,
borderRadius: 2,
borderColor: '#eeeeee',
borderStyle: 'dashed',
backgroundColor: '#fafafa',
color: '#bdbdbd',
transition: 'border .3s ease-in-out'
};
const activeStyle = {
borderColor: '#2196f3'
};
const acceptStyle = {
borderColor: '#00e676'
};
const rejectStyle = {
borderColor: '#ff1744'
};
function DropzoneComponent(props) {
const [files, setFiles] = useState([]);
const onDrop = useCallback(acceptedFiles => {
setFiles(acceptedFiles.map(file => Object.assign(file, {
preview: URL.createObjectURL(file)
})));
}, []);
const {
getRootProps,
getInputProps,
isDragActive,
isDragAccept,
isDragReject
} = useDropzone({
onDrop,
accept: 'image/jpeg, image/png'
});
const style = useMemo(() => ({
...baseStyle,
...(isDragActive ? activeStyle : {}),
...(isDragAccept ? acceptStyle : {}),
...(isDragReject ? rejectStyle : {})
}), [
isDragActive,
isDragReject,
isDragAccept
]);
const thumbs = files.map(file => (
<div key={file.name}>
<img
src={file.preview}
alt={file.name}
/>
</div>
));
// clean up
useEffect(() => () => {
files.forEach(file => URL.revokeObjectURL(file.preview));
}, [files]);
return (
<section>
<div {...getRootProps({style})}>
<input {...getInputProps()} />
<div>Drag and drop your images here.</div>
</div>
<aside>
{thumbs}
</aside>
</section>
)
}
export default DropzoneComponent;
Note: To avoid memory leaks, you will need to call URL.revokeObjectURL(file.preview)
to avoid storing the preview unnecessarily.
Now whenever a file (or files) has been dropped, the file will be appended to the state and a preview will be displayed.
In this tutorial, you were introduced to react-dropzone
and how it could be used in a React application to provide advanced drag and drop functionality to file uploads.
If you’d like to learn more about React, take a look at our How To Code in React.js series, or check out our React topic page for exercises and programming projects.
Thanks for learning with the DigitalOcean Community. Check out our offerings for compute, storage, networking, and managed databases.
This textbox defaults to using Markdown to format your answer.
You can type !ref in this text area to quickly search our full set of tutorials, documentation & marketplace offerings and insert the link!