在 React 中上传后预览多个图像的问题

问题描述 投票:0回答:1

我正在开发一个 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 进行样式设置

javascript reactjs next.js file-upload filereader
1个回答
0
投票

如果你想显示来自base64数据的图像,那么你需要在src信息中实际数据之前包含以下信息:

src="data:image/jpeg;charset=utf-8;base64,{your-data-here}

顺便说一句,为什么要在 UseState 挂钩中复制多个图像 src 并作为普通数组?

© www.soinside.com 2019 - 2024. All rights reserved.