A user can upload multiple images in the website. Users can delete an image, this was solved easily because of a function provided by the antd. But there is no certain function to update the existing image in the list of images. Like the image that the user wants to update, should be deleted and then the new selected image gets placed at that old image's position.
This is my AntD Upload Component:
<ImageUpload
uploadProps={{
...uploadProps,
name: name,
accept: "image/*",
listType: 'picture',
className: 'avatar-uploader bg-black',
showUploadList: showUploadList,
itemRender: (originNode, file, fileList, actions) => {
console.log(actions)
return (
<ImagePreview key={file.uid} title={file.name} size={file.size} type={file.type} imageUrl={file.thumbUrl} deleteButton={actions.remove} />
);
}
}}
title={title}
uploadButtonText={buttonText}
uploadButtonStyle={{ height: 100 }}
uploadButtonIcon={<ImageIcon style={{ fontSize: 30 }} />}
uploadWrapperStyle={{ width: width }}
showUploadButton={showUploadButton}
/>
Here's my <ImageUpload />
Component:
onst ImageUpload = ({
// Uploader props
uploadProps,
uploadWrapperStyle,
// Button props
title,
uploadingImage,
uploadButtonIcon,
uploadButtonText,
uploadButtonStyle = {},
onClick = () => {},
showUploadButton,
// Other props
loading,
skeletonHeight
}) => {
const [showImageViewer, setShowImageViewer] = useState(false)
const [imagesToCarousel, setImagesToCarousel] = useState([])
const [localFileList, setLocalFileList] = useState([])
const { fileList } = uploadProps
console.log('image');
const getBase64 = (file) =>
new Promise((resolve, reject) => {
const reader = new FileReader()
reader.readAsDataURL(file)
reader.onload = () => {
resolve(reader.result)
}
reader.onerror = (error) => reject('FR error', error)
})
useEffect(() => {
if (fileList) {
const imagesToSet = fileList
.filter((file) => (file.type ? !file.type.includes('pdf') : true))
.map(async (image) => {
let tmpItem = { ...image }
if (!tmpItem.url) {
const objUrl = await getBase64(image.originFileObj)
tmpItem = createUploadFileList(objUrl, false)
}
return tmpItem.url
})
Promise.all(imagesToSet).then((completed) => {
setImagesToCarousel(completed)
})
}
}, [fileList])
useEffect(() => {
setLocalFileList(fileList || [])
}, [fileList])
const uploadButton = () => (
<ImageUploadButtonWithThumbnail
uploadingImage={uploadingImage}
uploadButtonIcon={uploadButtonIcon}
uploadButtonText={uploadButtonText}
uploadButtonStyle={uploadButtonStyle}
onClick={onClick}
// image={images}
/>
)
return (
<UploadWrapper style={uploadWrapperStyle || {}}>
{loading ? (
<Skeleton height={skeletonHeight} />
) : (
<>
{title && <H7>{`${title}:`}</H7>}
<CustomUpload
fileList={localFileList}
{...uploadProps}
// onPreview={() => setShowImageViewer(true)}
>
{showUploadButton ? uploadButton() : null}
</CustomUpload>
<Modal
visible={showImageViewer}
footer={null}
onCancel={() => setShowImageViewer(false)}
centered
width='70%'
bodyStyle={{ height: '70vh', overflow: 'hidden' }}
>
<ImageCarousel images={imagesToCarousel} />
</Modal>
</>
)}
</UploadWrapper>
)
}
This is my ImagePreview Compoenent:
<div key={key} className="flex flex-wrap gap-4 sm:items-center p-4 border border-dashed m-4 rounded-lg">
<img className="h-[144px] w-[195px]" src={imageUrl} alt="" />
<div className="flex flex-col gap-8">
<div>
<h3 className="text-base">{title || 'Image Title'}</h3>
<div className="flex items-center gap-2 sm:gap-4 text-xs text-[#2E2B2EB2] opacity-75 mt-2">
<p className='mb-0'>{imgType?.map(char => <span className='uppercase'>{char}</span>) || 'Image Type'}</p>
<svg width="4" height="5" viewBox="0 0 4 5" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="2" cy="2.5" r="2" fill="#2E2B2E" fillOpacity="0.3" />
</svg>
<p className='mb-0 uppercase'>{size / 1000 + ' Kb' || 'Image Size'}</p>
</div>
</div>
<div className="flex gap-4 w-full">
<button className="flex items-center gap-2 rounded-md border border-[#2E2B2EB2] text-sm px-3 py-1 justify-center">
<svg width="12" height="15" viewBox="0 0 12 15" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M3.50033 11.3333H8.50033V6.33333H11.8337L6.00033 0.5L0.166992 6.33333H3.50033V11.3333ZM0.166992 13H11.8337V14.6667H0.166992V13Z" fill="#2E2B2E" />
</svg>
<span>Update</span>
</button>
<button onClick={deleteButton} className="flex items-center gap-2 rounded-md border border-[#2E2B2EB2] text-sm px-3 py-1 justify-center">
<svg width="12" height="15" viewBox="0 0 12 15" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M3.50033 11.3333H8.50033V6.33333H11.8337L6.00033 0.5L0.166992 6.33333H3.50033V11.3333ZM0.166992 13H11.8337V14.6667H0.166992V13Z" fill="#2E2B2E" />
</svg>
<span>Delete</span>
</button>
</div>
</div>
</div>