In this tutorial you are going to learn how create a file dropzone component from scratch using react.
We will discover how to open a file selection dialog in react using some nifty tricks.
Furthermore, we will learn how to listen for file drop events and use that to build a reusable dropzone component.
Ready?
Let’s get started!
Setting up a new React project with create-react-app
The first thing we do is setting up a new project. We will do so by using the create-react-app-cli.
To create a new project, use the following command:
create-react-app react-dropzone
Preparing the application
For this project to look good, I’ve adjusted the App.js a little bit.
It is now rendering the component we are going to create inside of a simple card:
The corresponding styles look something like this. Feel free to adjust any of this at is just a nice piece to present the dropzone component.
Creating the Dropzone component
Now that we have a nice foundation, it is time to start creating the dropzone component itself.
To do so, create a new directory inside of the src-folder. Inside of that directory, create two new files: Dropzone.js and Dropzone.css.
Next, create a new react component inside of Dropzone.js called Dropzone.
Basic structure
The HTML-structure of our component will be quite simple.
It is just a wrapper div containing an image a span.
To make it look like a dropzone, we are defining the CSS class “Dropzone”:
For the icon you can use any image you want. Just make sure to place it in the /public directory of your application and pass the filename to the src-attribure above.
You can find the icon used here at the material design website.
Because the icon is pure black, we are adjusting it’s opacity to look nice.
How to open a file dialog
Now it is time to implement some functionality.
First of all, we want the dropzone to open a file-selection-dialog when it is clicked. This dialog as to be provided by the browser (and the operating system) because we don’t have access to the file system from a website (which is actually a good thing).
The bad news is that there is no JavaScript API to open a file dialog.
The only way to open the dialog is by clicking on a HTML-input element with the type-attribute “file”.
Of course we don’t that. We want our dropzone-div to open the dialog when clicked.
Fortunately there is a little trick to make this work anyway. We just place the input-element somewhere, make it invisible and then click it using JavaScript.
This does look something like this:
We make the input invisible by using display: none.
To be able to reference the input element from code we are using a ref. Because we haven’t done so already, we need to initialize this.fileInputRef in the components constructor before we can use it.
Click event listener
To actually open the file dialog, we need to click on the input element using JavaScript.
Notice that we only do this if the property disabled is not true. This is a flag we are going to utilize later to disable our dropzone and reject any input.
For this method to execute, we need to call it when our dropzone is clicked. To do that, we are adding an onClick listener to the outer div of the component:
Notice, that we also set the cursor to “pointer” when the component is not disabled.
Furthermore we have to bind the openFileDialog to the component. Otherwise it would loose its this-reference.
We do so in the components’ constructor.
Defining an output property
Next, we need to implement the onFilesAdded() we referenced earlier. This method will be called when the file dialog is closed and files have been selected.
Because our component does not know what to do with these files, we are passing it to the parent component.
We do so by calling a property called onFilesAdded.
But before we can do so, we need to convert the files we received from a FileList to a plain JavaScript array, because that is much easier to work with.
To do that, we are defining the fileListToArray method we used in the mehtod above.
Finally, we have to bind the onFilesAdded method to the component because we are using this here.
Handling Drag & Drop Events
The dropzone component can now be used to select files by clicking it.
But it wouldn’t be called a dropzone if we can’t drop files onto it, right?
Fortunately it does not take much to add that functionality. All we need to do is to add three new methods called onDragOver, onDragLeave and onDrop.
Because all of these methods will need access to the components’ this, let’s go ahead and bind them first:
Notice that we also introduced a new state variable called “highlight” and set it to false. We will use it to highlight the dropzone when a file is dragged over it.
Let’s go ahead and register all these methods for their corresponding event:
Also, we are applying the CSS class “Highlight” in case the state variable “highlight” is true. Use any color you want!
Now it is time to implement each method…
onDragOver
The onDragOver method is quite simple.
All we need to is to set the highlight-state to true in case the component is not disabled.
We also need to call evt.preventDefault to prevent the default behavior of the browser.
onDragLeave
This mehtod is even simpler.
We just set the highlight-state to false.
We don’t even check if the component is disabled to not get stuck in the highlight-state in case the component is disabled when a file is dragged above it.
onDrop
In case a file is dropped onto the component, we need to notify the parent component about that. We do so by calling the onFilesAdded property.
Also, we set the highlight state to false.
If the component is disabled we do nothing.
The full dropzone component
Here is the full code for the dropzone component:
And here is the used stylesheet:
Conclusion
In this tutorial, you have learned how to create a file dropzone component from scratch.
I hope you liked this article. If you did, please share it with your friends and colleges. It would mean a lot to me!
You can find the full source code in the corresponding GitHub repository.
Thanks for reading!