Custom Upload Button, Image Preview and Image Upload with React Hooks

Ibrahim
3 min readJul 11, 2019

--

After I made this feature for my website, I decided to share the knowledge with everyone with this article.

To understand the whole article, I suggest you know JavaScript ES6, React and React Hooks before.

You can check the whole code below, and I’m gonna explain the rest after.

Handling Events

All the input on React must be handled, like changing the state or click button.

const [image, setImage] = useState({ preview: '', raw: '' })const handleChange = (e) => {
setImage({
preview: URL.createObjectURL(e.target.files[0]),
raw: e.target.files[0]
})
}

As you can see above, I made a function for handle change when user input or click the upload button. This function set initial value image depends on what user upload, in this case, image.

I set the image.preview with URL.createObjectUrl(e.target.files[0]). URL.createObjectURL() is built in javascript function which created new object URL represents the specified File. This new object can be used for display image on the screen.

And also I set the image.raw with e.target.files[0], it can be used later for uploading the image.

const handleUpload = async (e) => {
e.preventDefault()
const formData = new FormData()
formData.append('image', image.raw)
const config = { headers:
{'content-type': 'multipart/form-data'}
}
await uploadToBackend('endpoint', {image: image.raw}, config)
}

We came to handleUpload function, this function used for handling when user clicks the upload button. Inside the function, I append image.raw (which I set before) to formData. And also I create a config so backend can receive the image.

I’m not making backend upload tutorial in this article, I assume you already have backend server for handling it. Maybe later I will make another article for it. For now, just upload image configuration and call backend upload API from front-end.

HTML & CSS

For made custom upload button, I use some icons from Font Awesome and inline styling CSS.

<div>
<label htmlFor="upload-button">
{image.preview ? <img src={image.preview} /> : (
<>
<span className="fa-stack fa-2x mt-3 mb-2">
<i className="fas fa-circle fa-stack-2x" />
<i className="fas fa-store fa-stack-1x fa-inverse" />
</span>
<h5>Upload your photo</h5>
</>)}
</label>
<input type="file" id="upload-button" style={{ display: 'none' }} onChange={handleChange} />
<br />
<button onClick={handleUpload}>Upload</button>
</div>

The main idea for creating a custom upload input button is you should put whatever you want to replace the ugly input button inside label tag. After that give it id with whatever you want.

I made a ternary condition if user not yet choose image it will show the upload icon, and after user already choose image it will display an image on screen. User can re-choose image just by clicking the display image.

After that, give styles the real input file button with display: ‘none’ and id same as label id so this ugly button not appear on our screen. And also add onChange event with handleChange function we made before.

Finally, we create the upload button for saving this image on our server with onClick event which fire the handleUpload function.

Live demo

That's it! If you have any question we can have a conversation on response section below.

--

--