Ошибка при использовании хука useState в форме в реакции - PullRequest
0 голосов
/ 01 августа 2020

У меня возникла следующая проблема при запуске кода, мне нужна помощь, так как я не могу выяснить, в чем проблема, даже после того, как выяснил это в течение последних 4 дней.

1-й - согласно моему крючку product_specs , это массив из двух полей ввода, а именно поля спецификации и поля значения, и по одному полю каждого должно присутствовать с самого начала, когда загружается страница «http://localhost: 3000 / productupload», но я не получаю эти два поля с самого начала. Примечание. -AddClick и Remove Обработчик кликов добавляет или удаляет эти два поля ввода динамически. Изображение веб-страницы при загрузке формы прилагается ниже. enter image description here 2nd- when I type in my sub_category field I get errror TypeError: Cannot set property 'sub_category' of undefined enter image description here

My code for productupload page is

import FormInput from "../Forminput/forminput";
import CustomButton from "../Custombutton/custombutton";
import axios from "axios";

const ProductUpload = () => {
  const [sub_category, setSub_category] = useState("");

  const [product_name, setProduct_name] = useState("");

  const [product_image, setProduct_image] = useState("");

  const [product_specs, setProduct_specs] = useState([
    {
      specification: "",
      specvalue: "",
    },
  ]);
  
  const imageSelectedHandler = (event) => {
    setProduct_image({ product_image: event.target.files[0] });
  };

  // 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 = (e, i) => {
    const { name, value } = e.target;
    setSub_category({ ...sub_category, [name]: value });
    setProduct_name({ ...product_name, [name]: value });
    const p_specs = [...product_specs];
    product_specs[i][name] = value;
    setProduct_specs(p_specs); //This is 100% right.
  };
  //to add extra input field
  const addClick = () => {
    // setProduct_specs([...product_specs, { specification: "", specvalue: "" }]); //this is 100% right
    //also 100% correct alternative to above line
    const p_specs = [...product_specs];
    p_specs.push({ specification: "", specvalue: "" });
    setProduct_specs(p_specs);
  };
  //to remove extra input field
  const removeClick = (i) => {
    const p_specs = [...product_specs];
    p_specs.splice(i, 1);
    setProduct_specs(p_specs);
  };
  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 = () => {
    product_specs.map((item, i) => {
      return (
         handleChange (e, i)} value = {item.specification} label = "спецификация" требуется customwidth = "300px">  handleChange (e, i)} value = {item.specvalue} label = "значения спецификации, разделенные quomas" обязательно>  removeClick (i)} type = "button" value = "remove" style = {{margin: "12px"}}> Удалить  ); }); }; возвращение ( Добавить новый товар в базу  {/ * Выберите изображение  Загрузить  * /} {/ * согласно brad- type = "submit" value = "submit" это не должно использоваться, файл должен загружаться с формой submit * /} #     {createUI ()} Добавить поля  Загрузить товар    ); }; экспорт по умолчанию ProductUpload; 

код в моем маршруте продукта (с использованием express и multer для загрузки изображений

const express = require("express");
const router = express.Router();
const { check, validationResult } = require("express-validator");
const GridFsStorage = require("multer-gridfs-storage");
const multer = require("multer");
const connectDB = require("../../config/db");

const storage = new GridFsStorage({
  db: connectDB(),
});
const upload = multer({ storage });
module.exports = upload;
// @route GET api/Product
// @desc Test route
// @acess Public
router.get("/", (req, res) => res.send("Product route"));

// @route GET api/Product
// @desc staff will upload product to database
// @acess Private
router.post(
  "/",
  [
    check("subcategory", "subcategory is required").not().isEmpty(),
    check("product name", "product name is required").not().isEmpty(),
  ],
  upload.single("product_image"),
  async (req, res) => {
    const errors = validationResult(req);
    if (!errors.isEmpty()) {
      return res.status(400).json({ errors: errors.array() });
    }

    const {
      sub_category,
      product_name,
      product_image,
      product_specs,
    } = req.body;

    try {
      //See if product exists
      let product = await Product.findOne({ product_name }); // Product.findOne() is mongo db query

      if (product) {
        return res
          .status(400)
          .json({ errors: [{ msg: "Product already exists" }] });
      }

      //New product instance will be created and once user.save() command is given user will be created in mongodb database.
      product = new Product({
        sub_category,
        product_name,
        product_image,
        product_specs,
      });

      await product.save();
    } catch (err) {
      console.error(err.message);
      res.status(500).send("Server error");
    }
  }
);
module.exports = router;

Пожалуйста, помогите мне, я застрял в этом на 4 дня. Пожалуйста.

1 Ответ

0 голосов
/ 01 августа 2020

Спасибо за ответ, ребята, я нашел решение. Поделюсь с вами своим последним кодом. Спасибо

import FormInput from "../Forminput/forminput";
import CustomButton from "../Custombutton/custombutton";
import axios from "axios";

const ProductUpload = () => {
  const [sub_category, setSub_category] = useState({ sub_category: "" });

  const [product_name, setProduct_name] = useState({ product_name: "" });

  const [product_image, setProduct_image] = useState("");

  const [product_specs, setProduct_specs] = useState([
    {
      specification: "",
      specvalue: "",
    },
  ]);
  //note VIMP to add square bracket for array
  const imageSelectedHandler = (event) => {
    setProduct_image({ product_image: event.target.files[0] });
  };

  // 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 handleChange1 = (e) => {
    const { name, value } = e.target;

    setSub_category({ ...sub_category, [name]: value });
    setProduct_name({ ...product_name, [name]: value });
  };

  const handleChange2 = (e, i) => {
    const { name, value } = e.target;

    const p_specs = [...product_specs];
    p_specs[i][name] = value;
    setProduct_specs(p_specs); //This is 100% right.
  };

  //to add extra input field
  const addClick = () => {
    // setProduct_specs([...product_specs, { specification: "", specvalue: "" }]); //this is 100% right
    //also 100% correct alternative to above line
    const p_specs = [...product_specs];
    p_specs.push({ specification: "", specvalue: "" });
    setProduct_specs(p_specs);
  };
  //to remove extra input field
  const removeClick = (i) => {
    const p_specs = [...product_specs];
    p_specs.splice(i, 1);
    setProduct_specs(p_specs);
  };
  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((item, i) => {
      return (
        <div key={i} className="inputgroup">
          <FormInput
            type="text"
            name="specification"
            handleChange={(e) => handleChange2(e, i)}
            value={item.specification}
            label="specification"
            required
            customwidth="300px"
          ></FormInput>
          <FormInput
            type="text"
            name="specvalue"
            handleChange={(e) => handleChange2(e, i)}
            value={item.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}
            multiple={false}
            name="product_image"
          />
          {/* <CustomButton >
            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>
        <FormInput
          type="text"
          name="sub_category"
          handleChange={handleChange1}
          value={sub_category.sub_category}
          label="select from subcategories"
          required
        ></FormInput>

        <FormInput
          type="text"
          name="product_name"
          handleChange={handleChange1}
          value={product_name.product_name}
          label="product name"
          required
        ></FormInput>
        {console.log(product_name)}
        {console.log(product_specs)}
        {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;
...