Introduction
In this article, we will explore two different ways to display a preview of an image that has been uploaded in a React application. The first method uses the FileReader API to read the contents of the file and convert it into a data URL, which can then be used as the source for an <img>
element. The second method uses the URL.createObjectURL()
method, which creates a URL object that can be used as the src of an img element. Both methods will be demonstrated with code examples and explanations of how to implement them in a React component.
Displaying image preview using the FileReader API
To display an image that has been uploaded using the HTML <img>
tag and the File interface, you can use the FileReader API to read the file and set the src attribute of the <img>
tag to the result of the FileReader.readAsDataURL()
method.
FileReader API
FileReader is a JavaScript object that allows you to read the contents of a File or Blob object into memory. In this code snippet, it is used to read the contents of the file selected by the user and convert it into a data URL, which can be used as the source for an <img>
element.
The FileReader object has several methods for reading the contents of a file, such as readAsText()
, readAsArrayBuffer()
, readAsBinaryString()
, and readAsDataURL()
. In this case, the readAsDataURL()
method is used to read the contents of the file as a data URL, which is a string representation of the file’s data in the form of "data:<media type>;base64,<data>"
Once the FileReader object has finished reading the file, it triggers the onloadend event, which calls a callback function that sets the previewUrl
state variable to the result of the FileReader.
React Example
In a React component, you can use the useState
hook to store the file and the useEffect
hook to read the file when it changes. The src
attribute of the <img>
tag can then be set to the result of the FileReader.readAsDataURL()
method.
import React, { useState, useEffect } from 'react'
function ImagePreview() {
const [file, setFile] = useState(null)
const [previewUrl, setPreviewUrl] = useState(null)
useEffect(() => {
if (!file) {
return
}
const reader = new FileReader()
reader.onloadend = () => {
setPreviewUrl(reader.result)
}
reader.readAsDataURL(file)
}, [file])
return (
<>
<input type="file" onChange={(e) => setFile(e.target.files[0])} />
{previewUrl && <img src={previewUrl} alt="Preview" />}
</>
)
}
export default ImagePreview
In this example, when the file input’s onChange
event is triggered, the selected file is set in the component’s state using the setFile function. The useEffect
hook is used to read the file when it changes, by setting the src attribute of the <img>
tag to the result of the FileReader.readAsDataURL()
method, which is the data URL of the selected file.
It’s also worth noting that you should handle the cases if the user did not select any file or the file is not an image file to prevent any error when trying to read it.
You do not need to use the useEffect
cleanup function when using the FileReader()
method because it does not create an object URL like URL.createObjectURL()
does. Instead, it reads the file and returns the result as a Data URL, which is stored in the previewUrl state. This means that there are no URLs to revoke when the component unmounts or the file changes.
Displaying image preview using URL.createObjectURL()
You can achieve the same result without using FileReader()
. One alternative way to do this is by using the URL.createObjectURL()
method, which creates a URL object that can be used as the src of an img element. Here’s an example of how you could modify the code to use this method:
function ImagePreview() {
const [file, setFile] = useState(null)
const [previewUrl, setPreviewUrl] = useState(null)
useEffect(() => {
if (!file) {
return
}
setPreviewUrl(URL.createObjectURL(file))
}, [file])
return (
<>
<input type="file" onChange={(e) => setFile(e.target.files[0])} />
{previewUrl && <img src={previewUrl} alt="Preview" />}
</>
)
}
It’s important to note that you should revoke the object URL with URL.revokeObjectURL(previewUrl)
when the component unmounts or the file changes, otherwise it can cause a memory leak.
useEffect(() => {
if (!file) {
return
}
setPreviewUrl(URL.createObjectURL(file))
return () => {
URL.revokeObjectURL(previewUrl)
}
}, [file])
The useEffect
hook returns a function that will be called when the component unmounts. Inside this function, we are revoking the object URL, cleaning up memory and avoiding any memory leaks.
Summary
In summary, this article discussed two ways to display a preview of an image upload in React: using the FileReader API and using the URL.createObjectURL()
method. The FileReader API allows for reading the contents of a file and converting it into a data URL, which can be used as the source for an <img>
element. The URL.createObjectURL()
method creates a URL object that can also be used as the src of an <img>
element. Both methods allow for the preview of an image before it is uploaded, but it’s important to handle cases when a file is not selected or is not an image file, and also to revoke the object URL to avoid memory leaks. Overall, it’s up to the developer to decide which method works best for their specific use case.