To implement a custom image upload and preview feature in a React component using TypeScript, you can follow these steps:
Step 1: Set Up the Component
First, create a state to handle the selected file and its preview URL.
import React, { useState } from 'react';
const ImageUpload: React.FC = () => {
const [selectedImage, setSelectedImage] = useState<File | null>(null);
const [previewUrl, setPreviewUrl] = useState<string | null>(null);
const handleImageChange = (e: React.ChangeEvent<HTMLInputElement>) => {
const file = e.target.files?.[0];
if (file) {
setSelectedImage(file);
const objectUrl = URL.createObjectURL(file);
setPreviewUrl(objectUrl);
}
};
const handleImageRemove = () => {
setSelectedImage(null);
setPreviewUrl(null);
};
return (
<div>
<input
type="file"
accept="image/*"
onChange={handleImageChange}
style={{ display: 'none' }}
id="upload-input"
/>
<label htmlFor="upload-input" className="cursor-pointer">
<div className="upload-button">Upload Image</div>
</label>
{previewUrl && (
<div className="preview-container">
<img src={previewUrl} alt="Preview" className="preview-image" />
<button onClick={handleImageRemove} className="remove-button">
Remove Image
</button>
</div>
)}
</div>
);
};
export default ImageUpload;
Step 2: Styling the Component
You can add styles for the custom upload button and preview section. If you’re using Tailwind CSS, the styles might look something like this:
.upload-button {
padding: 8px 16px;
background-color: #4a90e2;
color: white;
border-radius: 4px;
text-align: center;
}
.preview-container {
margin-top: 16px;
}
.preview-image {
width: 100%;
max-width: 300px;
height: auto;
border-radius: 8px;
display: block;
}
.remove-button {
margin-top: 8px;
padding: 4px 8px;
background-color: #e74c3c;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
}
Step 3: Integrating Icons (Optional)
Since you’re using the Lucide library for icons, you could replace the “Upload Image” text and remove button with icons:
import { Upload, Trash2 } from 'lucide-react';
<label htmlFor="upload-input" className="cursor-pointer">
<Upload className="icon" />
</label>
<button onClick={handleImageRemove} className="remove-button">
<Trash2 className="icon" />
</button>
Final Touches
Ensure to clean up the object URL to avoid memory leaks when the component unmounts:
React.useEffect(() => {
return () => {
if (previewUrl) {
URL.revokeObjectURL(previewUrl);
}
};
}, [previewUrl]);
This setup will give you a clean and customizable image upload with a preview feature.
36