我正在开发一个 React 组件,它允许用户编辑产品和上传图像。虽然我能够正确设置和预览单个图像,但在预览多个图像时遇到问题。具体来说,图像在上传后不会按预期显示。在第 78 行中,console.log 确实记录了 Base 64 图像的数组,但我不知道为什么它不预览它
这是我的代码片段:
"use client"
import { usePathname } from 'next/navigation'
import React, { useState } from 'react'
import { useEffect } from 'react'
import axios from 'axios'
import { OrbitProgress } from 'react-loading-indicators'
import Image from 'next/image'
import { render } from 'react-dom'
const EditContent = () => {
// Get Data //
const path = usePathname();
const pathQeury = path.split("/");
const id = pathQeury[3];
const [fetched,setFetched] = useState(false);
const [products,setProducts] = useState([])
useEffect(() => {
axios.get(`/api/OneProductGet/${id}`)
.then((response) =>
{setProducts(response.data);
setFetched(true);
})
.catch((error) => console.error(error))
},[id])
console.log(products)
//-------------------------------------------//
// Data //
const [title, setTitle] = useState("");
const [description, setDescription] = useState("");
const [price, setPrice] = useState(0);
const [singleImage, setSingleImage] = useState(null);
const [multipleImages, setMultipleImages] = useState([]);
const [SingleImageSrc, setSingleImageSrc] = useState();
const [MultipleImageSrc, setMultipleImageSrc] = useState([]);
let MultipleImagesSrc = [];
let MultipleImages = [];
//------------------------------------------------------//
// Tranforme Single Image Data To src //
useEffect(() => {
if(singleImage){
const render = new FileReader();
render.onload = (e) => {
setSingleImageSrc(e.target.result);
}
render.readAsDataURL(singleImage);
}
else{
setSingleImageSrc(products[0]?.images[0]);
}
},[singleImage,products[0]])
console.log(SingleImageSrc)
//-------------------------------------//
// Function Of Handling Multiple Images //
MultipleImages.push(...multipleImages);
useEffect(() => {
if(MultipleImages){
MultipleImages.map((image) => {
const render = new FileReader();
render.onload = (e) => {
setMultipleImageSrc(e.target.result);
}
render.readAsDataURL(image);
MultipleImagesSrc.push(MultipleImageSrc);
})
}
console.log(MultipleImagesSrc)
},[MultipleImages])
//--------------------------------------//
// Function Of Handling Data //
async function handleSubmit(){
const formData = new FormData();
formData.append('title', title);
formData.append('description', description);
formData.append('price', price);
formData.append('singleImage', singleImage);
formData.append('multipleImages', multipleImages);
}
if (!fetched){
return(
<div className='flex justify-center items-center bg-white w-full m-5 rounded-lg ml-0 p-5'>
<OrbitProgress color="#1e3a8a" size="medium" text="" textColor="" />
</div>
);
}
return (
<div className=' bg-white w-full m-5 rounded-lg ml-0 p-5'>
<h1 className=' ml-2 text-3xl mb-4 font-semibold text-blue-900'>Edit Product</h1>
<form className='flex flex-col gap-1' onSubmit={handleSubmit}>
<label className='ml-1 text-blue-900 '>
Product name <span className='text-red-500'>*</span>
</label>
<input required={true} className='mb-2 border p-1 rounded-lg' type="text" name="title" placeholder={products[0]?.name}/>
<label className='ml-1 text-blue-900 '>
Description
</label>
<textarea className='mb-2 border p-1 rounded-lg' name="content" rows="4" cols="50" placeholder={products[0]?.description} />
<label className='ml-1 text-blue-900 '>Price (in MAD) <span className='text-red-500'>*</span></label>
<input required={true} className='mb-2 border p-1 rounded-lg' type="number" name="price" placeholder={products[0]?.price} />
<label className='text-blue-900'>Main Product Image <span className='text-red-500'>*</span></label>
<div className='grid grid-cols-4 gap-3'>
{ SingleImageSrc? (
<div className='relative group h-full w-full flex rounded-xl overflow-hidden border-2'>
<img
src={SingleImageSrc}
alt='hello'
></img>
<div className='group-hover:opacity-20 transition-all bg-black h-full absolute opacity-0 w-full'></div>
<button className=' absolute right-0' onClick={() => {setSingleImageSrc(undefined)}}>
<i class='bx bx-x text-red-500 invisible group-hover:visible absolute m-2 text-[30px] right-0'></i>
</button>
</div>
) : (<div className='hidden'></div>
)}
<div className='flex flex-col justify-center items-center text-center py-14 px-5 overflow-hidden relative border-dashed border-2 rounded-lg h-full '>
<i class='bx bx-cloud-upload text-blue-900 text-[3em]'></i>
<p className='w-[80%] '><span className='opacity-60'>Drop your images here or select</span> <span className='text-blue-900 opacity-100'>click to browse</span></p>
<input required={true} type="file" name="singleImage" accept="image/*" className='z-10 w-full h-full absolute opacity-0' onChange={(e) => {setSingleImage(e.target.files[0])}}/>
</div>
</div>
<label className='text-blue-900'>Product Images <span className='text-red-500'>*</span></label>
<div className='grid grid-cols-4'>
{ MultipleImagesSrc.length > 0 ? (
MultipleImagesSrc.map((image, i) => (
<div key={i} className='relative group h-[232px] w-full rounded-xl overflow-hidden border-2'>
<img
src={image} // Properly setting the base64 string here
className='w-full h-full absolute'
alt={`image-${i}`} // Giving a unique alt attribute
/>
<div className='group-hover:opacity-20 transition-all bg-black h-full absolute opacity-0 w-full'></div>
<button className='absolute right-0' onClick={() => {MultipleImagesSrc.splice(i, 1)}}>
<i className='bx bx-x text-red-500 invisible group-hover:visible absolute m-2 text-[30px] right-0'></i>
</button>
</div>
))
) : (
<div className='hidden'></div>
)}
<div className='flex flex-col justify-center items-center text-center py-14 px-5 overflow-hidden relative border h-fit '>
<i class='bx bx-cloud-upload text-blue-900 text-[3em]'></i>
<p className='w-[80%] '><span className='opacity-60'>Drop your images here or select</span> <span className='text-blue-900 opacity-100'>click to browse</span></p>
<input required={true} type="file" name="singleImage" accept="image/*" className='z-10 w-full h-full absolute opacity-0' multiple onChange={(e) => {setMultipleImages(e.target.files)}}/>
</div>
</div>
<input type="submit" value="save" className='bg-blue-900 w-fit text-white pb-1 px-3 rounded-lg ' />
</form>
</div>
)
}
export default EditContent
在检查 MultipleImagesSrc 包含图像的 Base 64 之后,我尝试映射 MultipleImagesSrc,但它没有预览它
问题:
多张图片上传后未立即按预期显示。我怀疑这可能与我处理图像预览的状态更新的方式有关。 当前渲染 MultipleImagesSrc 的方法可能无法正常工作。
环境:
Next.js 反应 使用 Tailwind CSS 进行样式设置
如果你想显示来自base64数据的图像,那么你需要在src信息中实际数据之前包含以下信息:
src="data:image/jpeg;charset=utf-8;base64,{your-data-here}
顺便说一句,为什么要在 UseState 挂钩中复制多个图像 src 并作为普通数组?