错误:重新渲染过多。 React限制了渲染次数以防止无限循环。由于setState

时间:2020-07-29 19:36:20

标签: reactjs setstate

Line 924: Char 34: runtime error: addition of unsigned offset to 0x602000000010 overflowed to 0x60200000000c (stl_vector.h) SUMMARY: UndefinedBehaviorSanitizer: undefined-behavior /usr/bin/../lib/gcc/x86_64-linux-gnu/8/../../../../include/c++/8/bits/stl_vector.h:933:34 中可能存在问题,有人可以告诉我我做错了什么导致代码渲染。还想知道以某种状态存储图像是否有错误。

代码摘要:

  1. 我正在从输入字段添加图像,setFormData
  2. 会对此加以注意。
  3. 我想知道需要imageSelectedHandler吗?甚至不使用我就能将表格和图像一起提交?
  4. 我还添加了新的输入字段,每次用户单击时,添加规格按钮。这是通过addClick和removeClick处理程序
  5. handleChange处理程序负责单个输入输入场。

请帮助某人。

imageUploadHandler

包含@AKX建议的更改的代码

import React, { useState } from "react";
import FormInput from "../Forminput/forminput";
import CustomButton from "../Custombutton/custombutton";
import axios from "axios";

const ProductUpload = () => {
  const [formData, setFormData] = useState({
    sub_category: null,
    product_name: null,
    product_image: null,
    product_specs: [{ specification: "", specvalue: "" }],
  });

  const { sub_category, product_name, product_image, product_specs } = formData;

  const imageSelectedHandler = (event) => {
    setFormData((prevState) => ({
      product_image: event.target.files[0],
      sub_category: { ...prevState.sub_category },
      product_name: { ...prevState.product_name },
      product_specs: [
        ...prevState.product_specs,
        { specification: "", specvalue: "" },
      ],
    }));
  };

  const imageUploadHandler = () => {
    const fd = new FormData();
    fd.append("product_image", product_image, product_image.name); //.name is Imp as name is property of file
  };
  const handleChange = (i, e) => {
    const { name, value } = e.target;
    product_specs[i] = { ...product_specs[i], [name]: value };
    setFormData({ product_specs }); //TO BE CHECKED
  };
  //to add extra input field
  const addClick = () => {
    setFormData((prevState) => ({
      sub_category: { ...prevState.sub_category },
      product_image: { ...prevState.image },
      product_name: { ...prevState.product_name },
      product_specs: [
        ...prevState.product_specs,
        { specification: "", specvalue: "" },
      ],
    }));
  };
  //to remove extra input field
  const removeClick = (i) => {
    product_specs.splice(i, 1);
    setFormData((prevState) => {
      return {
        sub_category: { ...prevState.sub_category },
        product_image: { ...prevState.image },
        product_name: { ...prevState.product_name },
        product_specs: [
          ...prevState.product_specs,
          { specification: "", specvalue: "" },
        ],
      };
    });
  };
  const handleSubmit = async (event) => {
    event.preventDefault();
    const newProduct = {
      sub_category,
      product_name,
      product_image,
      product_specs,
    };
    try {
      const config = {
        headers: {
          "Content-Type": "application/json",
        },
      };
      const body = JSON.stringify(newProduct);
      const res = await axios.post("/api/product", body, config);
      console.log(res.data);
    } catch (error) {
      console.error(error.response.data);
    }
  };
  const createUI = () => {
    return product_specs.map((el, i) => (
      <div key={i} className="inputgroup">
        <FormInput
          type="text"
          name="specification"
          handleChange={handleChange}
          value={el.specification}
          label="specification"
          required
          customwidth="300px"
        ></FormInput>
        <FormInput
          type="text"
          name="specvalue"
          handleChange={handleChange}
          value={el.specvalue}
          label="specification values seperated by quomas"
          required
        ></FormInput>
        <CustomButton
          onClick={removeClick(i)}
          type="button"
          value="remove"
          style={{ margin: "12px" }}
        >
          Remove
        </CustomButton>
      </div>
    ));
  };
  return (
    <div className="container">
      <form
        action="/upload"
        method="post"
        className="form"
        onSubmit={handleSubmit}
        encType="multipart/form-data"
      >
        <h3 style={{ color: "roboto, sans-serif" }}>
          Add new product to the database
        </h3>
        <div
          style={{
            display: "flex",
            height: "200px",
            width: "200px",
            border: "2px solid #DADCE0",
            borderRadius: "6px",
            position: "relative",
          }}
        >
          <input
            style={{ display: "none" }}
            type="file"
            accept="image/*"
            onChange={imageSelectedHandler}
            ref={(fileInput) => (this.fileInput = fileInput)}
            multiple={false}
            name="product_image"
          />
          <CustomButton onClick={() => this.fileInput.click()}>
            Select Image
          </CustomButton>
          <CustomButton onClick={imageUploadHandler}>Upload</CustomButton>

          {/*as per brad- type = "submit" value="submit"  this should not be used, file should upload with the form submit */}
          <div>
            <img
              style={{
                width: "100%",
                height: "100%",
              }}
              alt="#"
            />
          </div>
        </div>

        {createUI()}
        <div>
          <CustomButton
            onClick={addClick}
            type="button"
            style={{ margin: "14px" }}
          >
            Add More Fields
          </CustomButton>
          <CustomButton type="submit" style={{ margin: "12px" }}>
            Upload Product
          </CustomButton>
        </div>
      </form>
    </div>
  );
};

export default ProductUpload;

1 个答案:

答案 0 :(得分:0)

Ciao,我从未见过像这样在prevState钩子中使用useState的情况。基本上,当您传播prevState时,就像在说:“为所有状态元素保留相同的值”,然后逗号,然后是该状态的新值列表。

因此,不必在当前状态下重新分配相同的prevState值(因为它已经具有了!)。因此,我认为您应该像这样修改代码:

const imageSelectedHandler = (event) => {
  let new_product_specs = formData.product_specs;
  new_product_specs.push({ specification: "", specvalue: "" });
  setFormData((prevState) => ({
     ...prevState,
     product_image: event.target.files[0],
     product_specs: new_product_specs
   }));
};

关于imageUploadHandler的问题,我认为不需要提交表格。但是我不确定100%。