Image upload is one of the important and most used features in your web application. Let's take an example of facebook when you have to update your profile picture, you need to upload an image so that facebook can use it as your profile picture.
Today we will learn to build a simple image uploader which enables the user to select the image and display it in the browser. I hope it will be fun going through the tutorial and getting something out of it 😁. Let's go.
Setting up the project
For setting up your project, you can use either create-react-app or also you can go to CodeSandBox.
After creating your project, at first, let's create a simple file input which accepts images for upload
import React from "react";
import ReactDOM from "react-dom";
import "./styles.css";
function App() {
return (
<div className="App">
<input type="file" accept="image/*" multiple = "false" />
</div>
);
}
Here we are creating a file input that accepts only images and will allow uploading only one file at a time.
Now, let's create a container where the uploaded image will be displayed.
function App() {
return (
<div className="App">
<input type="file" accept="image/*" multiple = "false"/>
<div
style={{
height: "60px",
width: "60px",
border: "2px dashed black"
}}
>
<img
style={{
width: "100%",
height: "100%",
position: "absolute"
}}
/>
</div>
</div>
);
}
Here, we created a container where the image that is uploaded will be shown and also in the future, will be used as the image upload button.
**I wrote the inline styles for tutorial purposes.
Now the fun part let's add an onChange
handler in the image input and then access the image file in the handleImageUpload
method.
function App() {
const handleImageUpload = e => {
const [file] = e.target.files;
if (file) {
console.log(file);
}
};
return (
<div className="App">
<input type="file" accept="image/*" onChange={handleImageUpload} multiple = "false" />
<div
style={{
height: "60px",
width: "60px",
border: "1px dashed black"
}}
>
<img
style={{
width: "100%",
height: "100%",
position: "absolute"
}}
/>
</div>
</div>
);
}
We attach an handleImageUpload
method to the onChange event in the file input we created. In the handleImageUpload
method we get an e
(event) object which gives access to the list of files uploaded via the file input we created. We are uploading only one image so we will be accessing the first file from the FileList
and display the file for now.
Now we will attach a ref
to the img
we created where we can display the uploaded image using the useRef()
hook.
function App() {
const uploadedImage = React.useRef(null);
const handleImageUpload = e => {
const [file] = e.target.files;
if (file) {
console.log(file);
}
};
return (
<div className="App">
<input type="file" accept="image/*" onChange={handleImageUpload} />
<div
style={{
height: "60px",
width: "60px",
border: "1px dashed black"
}}
>
<img
ref={uploadedImage}
style={{
width: "100%",
height: "100%",
position: "absolute"
}}
/>
</div>
</div>
);
}
Now we will be using the FileReader
constructor in order to read the content of the file and will attach the content to the img
we attached the ref
to.
function App() {
const uploadedImage = React.useRef(null);
const handleImageUpload = e => {
const [file] = e.target.files;
if (file) {
const reader = new FileReader();
const {current} = uploadedImage;
current.file = file;
reader.onload = (e) => {
current.src = e.target.result;
}
reader.readAsDataURL(file);
}
};
return (
<div className="App">
<input type="file" accept="image/*" onChange={handleImageUpload} />
<div
style={{
height: "60px",
width: "60px",
border: "1px dashed black"
}}
>
<img
ref={uploadedImage}
style={{
width: "100%",
height: "100%",
position: "absolute"
}}
/>
</div>
</div>
);
}
In the handleImageUpload
method we create a reader
using FileReader
constructor and then select the current
from the uploadedImage
ref which represents the img
element. We then attach an onload
event listener to the reader
we created which when loaded will attach the file url it will read to the img
element. We then read the file as URL using the reader.readAsDataURL()
method and pass the file
selected into it.
So let's see our progress till now
Now lets remove that ugly input button and use the box created as the image uploader
function App() {
const uploadedImage = React.useRef(null);
const imageUploader = React.useRef(null);
const handleImageUpload = e => {
const [file] = e.target.files;
if (file) {
const reader = new FileReader();
const { current } = uploadedImage;
current.file = file;
reader.onload = e => {
current.src = e.target.result;
};
reader.readAsDataURL(file);
}
};
return (
<div
style={{
display: "flex",
flexDirection: "column",
alignItems: "center",
justifyContent: "center"
}}
>
<input
type="file"
accept="image/*"
onChange={handleImageUpload}
ref={imageUploader}
style={{
display: "none"
}}
/>
<div
style={{
height: "60px",
width: "60px",
border: "1px dashed black"
}}
onClick={() => imageUploader.current.click()}
>
<img
ref={uploadedImage}
style={{
width: "100%",
height: "100%",
position: "absolute"
}}
/>
</div>
Click to upload Image
</div>
);
}
Here we create a imageUploader
ref and assign it to the file input, we then hide the ugly file input element using the css display:none
. After that we will attach an onClick
listener to the div which clicks the file input when the div is clicked, so that means the image can be uploaded when the div is clicked. We apply some styling to our parent container so that everything appears in the center, now lets see how our output looks like.
You can find the completed code here
Thankyou.
You can also follow me on Twitter.
Top comments (9)
Hi Asim, that was a very clear way of explaining it. I've got a few questions:
e.target.result
supposed to return? On my end it isundefined
.ref
?I want to delete the picture i have uploaded is there a solution for that too?
Nice article! Why did you decide to use
useRef
instead of saving the file to state? @asimdahillI'm also wondering the same. Furthermore, Jake did you mean internal Component state or global state via something like Context or Redux?
hey,
A great article, I had one query, can you help me with how to clear the select image, like a clear button which will remove / clear selected image.
Thanks
I want to delete the picture i have uploaded is there a solution for that too?
Is there a way to save these images to a database so the user keeps the image displayed
Good question, and thanks for participating in the discussion. I'll have to defer to the author. But, it would appear that this article might be focused on just the client-side of things - the components, etc. Not so much the server side. For that one could consider a 'ready-made' solution such as Cloudinary, if it's an immediate need.
I want to delete the picture i have uploaded is there a solution for that too?