← Back toDrag and drop in React

Read the content of the dropped file

Written byPhuoc Nguyen
Created
30 Nov, 2023
Tags
FileReader API, HTML 5 drag and drop
In our previous post, we learned how to provide a visual representation of uploaded images before submitting them. This not only enhances the user experience but also gives users more control over their uploads.
We can do a similar thing for text files. Reading and displaying the content of text files can be useful in many real-life scenarios. For example, code editors often have a drag-and-drop feature to open or import files into the editor. By reading and showing the content of the dropped file, code editors can provide an easy way for developers to preview and edit their code.
Most popular markdown editors allow you to import contents from markdown files. You can simply drag and drop your markdown file into the editor window, and it will automatically import the contents of your file into the editor. This feature saves time and effort by eliminating the need to copy and paste content into the editor manually. It makes it easier for writers and developers to work with their existing content without worrying about formatting or converting their files manually.
Email clients also allow users to attach text files to their emails. By displaying the content of the attached file, email clients can give recipients a quick preview of what's inside without requiring them to download the file first.
In this post, we'll learn how to implement this functionality with React. We'll demonstrate by appending the content of a textarea when users drop a text file onto it. Let's dive in!

Filtering text files

To retrieve information about dropped files, we need to handle two different events. To do this, we define two event handlers: `handleDrop` and `handleDragOver`. The `handleDrop` function handles the `drop` event, while the `handleDragOver` function handles the `dragover` event.
tsx
<textarea
placeholder="Drop a text file here"
onDrop={handleDrop}
onDragOver={handleDragOver}
/>
When a user drags files over the text area, the `handleDragOver` function is called. This function takes care of the `drag` event and also stops the default behavior of opening the file in the browser. In other words, it ensures that the file is not accidentally opened when the user is trying to drag it.
ts
const handleDragOver = (e: DragEvent) => {
e.preventDefault();
};
On the other hand, if a user drops one or more files onto the text area, the `handleDrop` function is triggered. This function prevents the browser from automatically opening the dropped file.
ts
const handleDrop = (e: DragEvent) => {
e.preventDefault();
// Do something with `e.dataTransfer.files` ...
};
When users drop files onto the text area, we can retrieve information about them using the `e.dataTransfer.files` property. This property returns a `FileList` object that contains details about each dropped file, such as the file name, size, type, and last modified date.
To filter out only the text files from `dataTransfer.files`, we can use the `filter()` method. We create a new array that contains only the text files by checking if each file's type is equal to `'text/plain'`. This ensures that only text files are included in the `textFiles` array, and any other file types are ignored.
ts
const files = Array.from(e.dataTransfer.files);
const textFiles = files.filter(file => file.type === 'text/plain');
Now that we have our filtered array of text files, we can read their contents and display them in our application as required. In the next section, we'll explore how to do this.

Reading the content of a text file

If you need to read the contents of a text file in a web application, the `FileReader` API is the way to go. This API allows you to read files asynchronously, meaning that you can load and manipulate files without blocking your application.
To get started, create a new instance of `FileReader` and select the file you want to read. Then, use the `readAsText()` method to begin reading the file's contents as a text string.
Once the file has been successfully read, a `load` event will be fired. You can set up an event handler to handle this event and access the contents of your text file using the `reader.result` property. This gives you the flexibility to perform any necessary operations on the file's contents, such as appending it to a text area.
Here's an example code snippet to help you get started with the `FileReader` API:
ts
const reader = new FileReader();
reader.readAsText(textFiles[0]);
reader.addEventListener('load', () => {
const content = reader.result.toString();
setValue(value => value + '\n' + content);
});
Take a look at the demo below:

Inserting content at the current cursor position

If you want to make your application more user-friendly, you may want to consider inserting content at the current cursor position of the text area, rather than appending the content every time.
To achieve this, we can use the `useRef()` hook to create a reference to the text area.
tsx
const textareaRef = React.useRef();

// Render
<textarea ref={textareaRef} />
To keep track of where the cursor is in a text area, we can use the `selectionStart` and `selectionEnd` properties. These properties tell us where the selected text starts and ends.
With this information, we can insert new content at the current cursor position. First, we need to split our existing value into two parts: the text before the cursor and the text after. Then, we can combine these parts with our new content to create the updated value.
Here's an example code snippet to help you see how it works:
ts
reader.addEventListener('load', () => {
const content = reader.result.toString();
const textarea = textareaRef.current;

if (document.activeElement === textarea) {
const startPos = textarea.selectionStart;
const endPos = textarea.selectionEnd;
const newValue =
value.substring(0, startPos) +
content +
value.substring(endPos, value.length);
setValue(newValue);
} else {
setValue(value => value + '\n' + content);
}
});
In this example, we grab the text area by using the `current` property and then retrieve its `selectionStart` and `selectionEnd` properties inside the `load` event handler function. By doing so, we're able to concatenate our existing value string with our new content string using these selection positions to insert the new content at the current cursor position.
It's important to note that these checks are only performed if the user is currently focused on the text area. We do this by checking the `activeElement` property of the `document` against the text area element. If they don't match, we append the content to the end of the text area as we did in the previous section.
With this implementation, users can drop a text file onto their desired location within the text area instead of just appending it to the end.
Give it a try! Move the cursor to the desired location within the text area, and then drag a text file. The content of the text file will be inserted at the current cursor position.

Conclusion

In this post, we explored how to add a drag-and-drop feature for text files in a React application. We showed you how to filter text files from the list of dropped files and read their contents using the `FileReader` API.
This feature can be very helpful in various real-life scenarios where users need to upload or preview text files. By providing an easy way to read and display the content of text files, we can improve user experience and save them time.
We hope that this post has been useful in understanding how to work with dropped text files in React. As always, feel free to experiment with the code and customize it to fit your specific needs.

See also

If you found this post helpful, please consider giving the repository a star on GitHub or sharing the post on your favorite social networks 😍. Your support would mean a lot to me!

Questions? 🙋

Do you have any questions about front-end development? If so, feel free to create a new issue on GitHub using the button below. I'm happy to help with any topic you'd like to learn more about, even beyond what's covered in this post.
While I have a long list of upcoming topics, I'm always eager to prioritize your questions and ideas for future content. Let's learn and grow together! Sharing knowledge is the best way to elevate ourselves 🥷.
Ask me questions

Recent posts ⚡

Newsletter 🔔

If you're into front-end technologies and you want to see more of the content I'm creating, then you might want to consider subscribing to my newsletter.
By subscribing, you'll be the first to know about new articles, products, and exclusive promotions.
Don't worry, I won't spam you. And if you ever change your mind, you can unsubscribe at any time.
Phước Nguyễn