When it comes to the usage of any website, user input is key and in many sites today a user may be required for one reason or another to upload a file to the website. This can be anything from images for a new user profile to diagnostic files needed to help users troubleshooting on a help forum. For this reason, it is crucial to make the file upload process as easy and seamless for the user. You need to allow the user to quickly access their file picker, choose files, upload them, and get feedback on the status of their upload. This is where react-uploady comes in to save the day.
The react-uploady library is built to be simple yet customizable and allows us to create and customize the view of our uploader to our liking. Developers using the library can keep it simple and just use it plug and play or they can also customize the entire upload flow. For this article, we’ll be making use of Ant Design which provides a library of well built and customizable React UI components to create a simple yet appealing uploader component that allows us to open the file explorer and pick out files to upload.
You may be wondering why a developer may be inclined to use react-uploady over other file uploader libraries so let us look at some of the advantages react-uploady has that other libraries don’t.
First, let’s bootstrap our application with create-react-app, if you do not have it installed already you can do so by running:
npm install -g create-react-app
Now you can create your application by running:
create-react-app react-uploady-demo
We have a few dependencies that we will need for our application, to install them, run this command:
yarn add @rpldy/uploady @rpldy/sender antd
These packages are:
Uploader
componentCreate an Uploader.js
file and create an Uploader
functional component as shown below:
//Uploader.js import React, { useState, useCallback, useContext } from "react"; import "./App.css"; import Uploady, { useItemProgressListener, UploadyContext } from "@rpldy/uploady"; import { createMockSender } from "@rpldy/sender"; import { Button, Progress } from "antd"; const Uploader = () => { return ( <Uploady destination={{ url: "http://mock-server.com" }} enhancer={mockEnhancer} > <div className="Uploader"> <CustomButton /> <br /> <br /> <UploadProgress /> </div> </Uploady> ); } const mockEnhancer = uploader => { const mockSender = createMockSender({ delay: 1000 }); uploader.update({ send: mockSender.send }); return uploader; }; export default Uploader;
In the code above we import the Uploady
component which is the context provider from react-uploady. It allows us to configure our upload options such as the destination as well as any enhancers we may want to add.
The destination
prop takes an object that configures the endpoint to which we will send the uploaded file. in our case, we are simply providing a URl but this is where you can set request parameters, methods, and headers that you may need for your request.
The enhancer
prop on the other hand takes an enhancer function which we can use to change the behavior of our uploader. For instance, this is where you can add a function that tells the uploader to retry any failed downloads. In our case, we are feeding in a mockEnhancer
function created using createMockSender
that tells our uploader that the upload has been successfully sent after 1000 milliseconds. For more on enhancers check out the documentation on enhancers.
You will have also noticed we have two missing components, CustomButton
and UploadProgress
, let us create these two now.
Our upload button is a simple functional component that is granted access to the UploadyContext
using React’s useContext
hook and uses it to open the native file browser to select a file to send to the server. This process is triggered by clicking a custom button from Ant Design which calls the handleUpload
function that we define in the component. To do this we add the following code into Uploader.js
:
const CustomButton = () => { const uploady = useContext(UploadyContext); const hanldeUpload = useCallback(()=> { uploady.showFileUpload(); },[uploady]); return <Button onClick={hanldeUpload} type="primary">Custom Upload Button</Button> }
Providing the user with feedback on how the upload process is going is key when trying to create a good user experience and a good way to do this is displaying the progress of the download through a progress bar or some similar UI. In our case, we will go with the Progress
component from Ant Design, specifically the circular variant, and this is how we can go about it.
Add the following functional component to Uploader.js
:
const UploadProgress = () => { const [progress, setProgess] = useState(0); const progressData = useItemProgressListener(); if (progressData && progressData.completed > progress) { setProgess(() => progressData.completed); } return ( progressData && ( <Progress type="circle" percent={progress} /> ) ); };
Four our progress UI we got the current progress from the uploader using the useItemProgressListener
hook from react-uploady. This hook listens for and captures the progress information of each download from the sender, we then save this progress into state and feed it into the Progress
component which will show the amount of the upload that has been done all the way to completion. We, of course, hide this component when there is no ongoing upload.
The last step for us is to add some CSS to ensure that our components are placed nicely in the browser then add our Uploader component to the main App.js
file so that it may be displayed. Add these few lines to App.css
to center the components and space them out a little:
.Uploader{ padding: 5rem; margin: 0 auto; }
Now let us update App.js
by replacing all the create-react-app boilerplate code with these few lines:
import './App.css'; import 'antd/dist/antd.css'; import Uploader from './Uploader' function App() { return ( <div className="App"> <Uploader /> </div> ); } export default App;
And that’s it! We are all set to go! Startup your application with yarn start
and watch the magic!
You can check out the final application here.
With this information, you are all set to get started using react-uploady in your React application to create intuitive user upload components. This is, however, just one method the package provides to upload files with the library also supporting drag and drop inputs as well as uploading files from a given URL. The library also supports a number of senders such as chunked XHR requests and using the TUS protocol. It would be almost impossible to take a deep dive into all the above methods in just a single article and I would recommend checking out the guides and documentation as you make use of react-uploady. The maintainers were also kind enough to create a Storybook with several examples of varying complexity.
There are, of course, other steps you may take to further improve your uploader’s UX such as creating resumable downloads and providing user feedback with toasts. Hopefully, you can build on the knowledge picked up in this article and you can look into these improvements and more.
Install LogRocket via npm or script tag. LogRocket.init()
must be called client-side, not
server-side
$ npm i --save logrocket // Code: import LogRocket from 'logrocket'; LogRocket.init('app/id');
// Add to your HTML: <script src="https://cdn.lr-ingest.com/LogRocket.min.js"></script> <script>window.LogRocket && window.LogRocket.init('app/id');</script>
Would you be interested in joining LogRocket's developer community?
Join LogRocket’s Content Advisory Board. You’ll help inform the type of content we create and get access to exclusive meetups, social accreditation, and swag.
Sign up nowLearn how to manage memory leaks in Rust, avoid unsafe behavior, and use tools like weak references to ensure efficient programs.
Bypass anti-bot measures in Node.js with curl-impersonate. Learn how it mimics browsers to overcome bot detection for web scraping.
Handle frontend data discrepancies with eventual consistency using WebSockets, Docker Compose, and practical code examples.
Efficient initializing is crucial to smooth-running websites. One way to optimize that process is through lazy initialization in Rust 1.80.