При попытке загрузить только одно изображение на значок изображения все значки обновляются одним и тем же изображением (это не то, что я хочу)

#redux #file-upload

#сокращение #загрузка файла

Вопрос:

Я хочу, чтобы при нажатии на один значок загружалось только одно изображение. Вместо этого все значки обновляются, когда я пытаюсь загрузить одно изображение только на один значок изображения. Может кто-нибудь помочь мне разобраться в этом. У меня такое чувство, что это потому, что я не использую уникальные идентификаторы для входного идентификатора, но я не уверен. Любая помощь будет оценена. Спасибо.

 import React, { useState } from "react";
import { Row, Col } from "../Grid";
import PropTypes from 'prop-types';

export default function Step1(props) {

 const [image_1, setImage_1] = useState({ preview_1: "", raw_1: "" });
 const [image_2, setImage_2] = useState({ preview_2: "", raw_2: "" });
 const [image_3, setImage_3] = useState({ preview_3: "", raw_3: "" });
 const [image_4, setImage_4] = useState({ preview_4: "", raw_4: "" });


 const handleLoadLocalFile = (event) => {
  event.preventDefault();
  const file_1 = event.target.files[0];
  const file_2 = event.target.files[0];
  const file_3 = event.target.files[0];
  const file_4 = event.target.files[0];
  const localImageUrl_1 = window.URL.createObjectURL(file_1);
  const localImageUrl_2 = window.URL.createObjectURL(file_2);
  const localImageUrl_3 = window.URL.createObjectURL(file_3);
  const localImageUrl_4 = window.URL.createObjectURL(file_4);
  
  if(event.target.files.length){
    setImage_1({
      preview_1: localImageUrl_1,
      raw_1: file_1
    })
    setImage_2({
      preview_2: localImageUrl_2,
      raw_2: file_2
    })
    setImage_3({
      preview_3: localImageUrl_3,
      raw_3: file_3
    })
    setImage_4({
      preview_4: localImageUrl_4,
      raw_4: file_4
    })
    props.onFileLoaded(localImageUrl_1);
    props.onFileLoaded(localImageUrl_2);
    props.onFileLoaded(localImageUrl_3);
    props.onFileLoaded(localImageUrl_4);
  }
}

const handleUpload = async event => {
event.preventDefault();
const formData = new FormData();
formData.append("image_1", image_1.raw_1)
formData.append("image_2", image_2.raw_2)
formData.append("image_3", image_3.raw_3)
formData.append("image_4", image_4.raw_4)
}

if(props.currentStep !== 1) {
  return null;
}
//   const [image, setImage] = useState({ preview: "", raw: "" });

//   const handleItemChange = e => {
//     if (e.target.files.length) {
//       setImage({
//         preview: URL.createObjectURL(e.target.files[0]),
//         raw: e.target.files[0]
//       });
//     }
//   };

//   const handleItemUpload = async e => {
//     e.preventDefault();
//     const formData = new FormData();
//     formData.append("image", image.raw);


//     await fetch("/api/additem", {
//       method: "POST",
//       headers: {
//         "Content-Type": "multipart/form-data"
//       },
//       body: formData
//     });
//   };
   
        //Markup for step 1 UI
        
      return(
        
      <Row>
      <Col size="md-6">

<div>  
<label htmlFor="upload-button" id="file_1">
  {image_1.preview_1 ? (
    <img src={image_1.preview_1} alt='dummy' width="100" height="100" />
  ) : (
     <img src={require("../../images/store.jpg")} style={{justifyContent: "center", alignItems: "center"}} alt="placeholder" width="100" height="100" />
    /* // <>
    //   <span className="fa-stack fa-2x mt-3 mb-2">
    //     <i className="fas fa-circle fa-stack-2x" />
    //     <i className="fas fa-store fa-stack-1x fa-inverse" />
    //   </span>
    //   {/* <h5 className="text-center">Upload your photo</h5> 
    // </> */
  )}
</label>
       <input 
       type="file" 
       id="upload-button"
       style={{ display: "none" }} 
       value={props.localImageUrl_1}
       onChange={handleLoadLocalFile} />
       <br/>
       <button onClick={handleUpload}>Upload</button>
      </div>       

  <div>
  <label htmlFor="upload-button" id="file_2">
    {image_2.preview_2 ? (
    <img src={image_2.preview_2} alt="dummy" width="100" height="100" />
    ) : (
    <img src={require("../../images/store.jpg")} style={{justifyContent: "center", alignItems: "center"}} alt="placeholder" width="100" height="100" />
    /* // <>
    //   <span className="fa-stack fa-2x mt-3 mb-2">
    //     <i className="fas fa-circle fa-stack-2x" />
    //     <i className="fas fa-store fa-stack-1x fa-inverse" />
    //   </span>
    //   {/* <h5 className="text-center">Upload your photo</h5> 
    // </> */
    )}
</label>
       <input 
       type="file" 
       id="upload-button" 
       style={{ display: "none" }} 
       value={props.localImageUrl_2}
       onChange={handleLoadLocalFile} />
       <br />
       <button onClick={handleUpload}>Upload</button>
       </div>
       <br />

  <div>
 <label htmlFor="upload-button" id="file_3">
 {image_3.preview_3 ? (
    <img src={image_3.preview_3} alt="dummy" width="100" height="100" />
    ) : (
    <img src={require("../../images/store.jpg")} style={{justifyContent: "center", alignItems: "center"}} alt="placeholder" width="100" height="100" />
    /* // <>
    //   <span className="fa-stack fa-2x mt-3 mb-2">
    //     <i className="fas fa-circle fa-stack-2x" />
    //     <i className="fas fa-store fa-stack-1x fa-inverse" />
    //   </span>
    //   {/* <h5 className="text-center">Upload your photo</h5>
    // </> */
    )}
</label>
       <input type="file" 
       id="upload-button" 
       style={{ display: "none" }} 
       value={props.localImageUrl_3}
       onChange={handleLoadLocalFile} /> 
       <br />
       <button onClick={handleUpload}>Upload</button>
       </div>
        

  <div>
  <label htmlFor="upload-button" id="file_4">
  {image_4.preview_4 ? (
    <img src={image_4.preview_4} alt="dummy" width="100" height="100" />
    ) : (
    <img src={require("../../images/store.jpg")} style={{justifyContent: "center", alignItems: "center"}} alt="placeholder" width="100" height="100" />
    /* // <>
    //   <span className="fa-stack fa-2x mt-3 mb-2">
    //     <i className="fas fa-circle fa-stack-2x" />
    //     <i className="fas fa-store fa-stack-1x fa-inverse" />
    //   </span>
    //   {/* <h5 className="text-center">Upload your photo</h5> 
    // </>
  )} */
    )}
</label>
       <input 
       type="file" 
       id="upload-button" 
       style={{ display: "none" }} 
       value={props.localImageUrl_4}
       onChange={handleLoadLocalFile} />
       <br />
       <button onClick={handleUpload}>Upload</button>
       </div>
       
      </Col>

            <Col size="md-6" fixed>

          <form>

          <label htmlFor="title">Title:</label>
          <input
          onChange={props.handleChange}
          value={props.title}
          name="title"
          type="text"
          className="form-control"
          placeholder="product title"
          id="title"
        />
        <br/>
        <br/>
        <br/>

        <label htmlFor="price">Price:</label>
        <input
          onChange={props.handleChange}
          value={props.price}
          name="price"
          type="text"
          className="form-control"
          placeholder="product price"
          id="price"
        />
        <br/>
        <br/>
        <br/>
           
           <label htmlFor="shelf">Shelf:</label>amp;nbsp;amp;nbsp;
           <select 
           onChange={props.handleChange}
           value={props.shelf}
           name="shelf"
           id="shelf" 
           >
        <option value="biscuits">Biscuits</option>
        <option value="breads">Breads</option>
        <option value="cakes">Cakes</option>
        <option value="pastries">Pastries</option>
        <option value="pizzas">Pizzas</option>
        <option value="signature">Signature</option>
        </select>


        </form>

        </Col>
        </Row>
        )
    }
    Step1.propTypes = {
      onFileLoaded: PropTypes.func.isRequired
    }
     
// export default Step1;
  

Ответ №1:

Ваша onClick функция одинакова handleClick для каждого изображения. Вызов этой функции добавляет все четыре файла formData , вызывая их загрузку.

 const handleUpload = async event => {
    event.preventDefault();
    const formData = new FormData();
    formData.append("image_1", image_1.raw_1)
    formData.append("image_2", image_2.raw_2)
    formData.append("image_3", image_3.raw_3)
    formData.append("image_4", image_4.raw_4)
}
  

Вам нужна функция, которая принимает изображение для добавления в качестве аргумента и добавляет только это одно изображение.

Вы создали много ненужных повторений кода, обрабатывая четыре изображения как отдельные состояния. Подумайте о том, как вы можете выполнить цикл от 1 до 4 и сделать то же самое для каждого числа. И как иметь функции, которые принимают число в качестве аргумента.

A handleUpload может выглядеть примерно так, если все 4 изображения были сохранены в массиве.

 const handleUpload = id => async event => {
    event.preventDefault();
    const formData = new FormData();
    formData.append(`image_${id}`, images[id].raw)
}