React: How to handle file uploads
4 November 2022 (Updated 4 November 2022)
Here’s an example of how to handle file uploads with React (CodeSandbox).
import { useRef, useState } from 'react'
const App: React.FC = () => {
const [selectedFile, setSelectedFile] = useState<File | null>(null)
const fileInputRef = useRef<HTMLInputElement | null>(null)
const [downloadLink, setDownloadLink] = useState<string | null>(null)
function handleAddAttachment() {
if (!fileInputRef.current) {
return
}
fileInputRef.current.click()
}
function handleRemoveAttachment() {
setSelectedFile(null)
if (downloadLink) {
window.URL.revokeObjectURL(downloadLink)
}
}
function handleFileChange(event: React.ChangeEvent<HTMLInputElement>) {
// event.target.files is a FileList object
// (https://developer.mozilla.org/en-US/docs/Web/API/FileList)
const files = event.target.files
// Each item in FileList is a File object
// https://developer.mozilla.org/en-US/docs/Web/API/File
const file = files && files[0] ? files[0] : null
console.log(file)
setSelectedFile(file)
if (file) {
setDownloadLink(window.URL.createObjectURL(file))
}
}
function getFileType(mimeType: string): string {
const subtype = mimeType.split('/')[1]
if (typeof subtype === 'undefined') {
return 'Unknown'
}
if (subtype.includes('ms-powerpoint')) {
return 'Powerpoint'
}
if (subtype.includes('ms-word')) {
return 'Word doc'
}
if (subtype.includes('ms-excel')) {
return 'Spreadsheet'
}
return subtype.toUpperCase()
}
return (
<main className="px-4 my-6">
<button
className="border border-gray-400 px-3"
onClick={handleAddAttachment}
>
Attach file
</button>
{selectedFile && (
<>
<button
className="block text-sm mt-1 text-red-600"
onClick={handleRemoveAttachment}
>
Remove file
</button>
{downloadLink && (
<a
href={downloadLink}
className="block text-sm mt-1 text-indigo-600"
download={selectedFile.name}
>
Download file
</a>
)}
</>
)}
<input
ref={fileInputRef}
type="file"
name="file"
onChange={handleFileChange}
className="hidden"
/>
{selectedFile && (
<div className="mt-4">
<h2 className="text-xl font-bold mb-1">File details</h2>
<ul className="list-disc pl-8">
<li>File name: {selectedFile.name}</li>
<li>File mime type: {selectedFile.type}</li>
<li>File type: {getFileType(selectedFile.type)}</li>
<li>File download link: {downloadLink}</li>
</ul>
</div>
)}
</main>
)
}
export default App
Tagged:
React patterns
Thanks for your comment 🙏. Once it's approved, it will appear here.
Leave a comment