While Updating product in react, it get updated on database but shows error saying " TypeError: Cannot read properties of undefined (reading 'img') "

Viewed 47

TypeError: Cannot read properties of undefined (reading 'img')

I receive this error while updating the product after it gets updated on the MongoDB database TypeError: Cannot read properties of undefined (reading 'img')

My codes are as follows:

Product.jsx

import { Link, useLocation } from "react-router-dom";
import "./product.css";
import Chart from "../../components/chart/Chart";
import { Publish } from "@material-ui/icons";
import { useSelector, useDispatch } from "react-redux";
import { useEffect, useMemo, useState } from "react";
import { userRequest } from "../../requestMethod";
import { updateProduct } from "../../redux/apiCalls";
import app from "../../firebase"
import {
  getStorage,
  ref,
  uploadBytesResumable,
  StorageRef,
  getDownloadURL,
} from "firebase/storage"
import axios from "axios";

export default function Product() {
  const location = useLocation();
  const productId = location.pathname.split("/")[2];
  const [pStats, setPStats] = useState([]);



const MONTHS = useMemo(
    () => [
      "Jan",
      "Feb",
      "Mar",
      "Apr",
      "May",
      "Jun",
      "Jul",
      "Agu",
      "Sep",
      "Oct",
      "Nov",
      "Dec",
    ],
    []
  );

  useEffect(() => {
    const getStats = async () => {
      try {
        const res = await userRequest.get("orders/income?pid=" + productId);
        const list = res.data.sort((a, b) => {
          return a._id - b._id
        })
        list.map((item) =>
          setPStats((prev) => [
            ...prev,
            { name: MONTHS[item._id - 1], Sales: item.total },
          ])
        );
      } catch (err) {
        console.log(err);
      }
    };
    getStats();
  }, [productId, MONTHS]);




const product = useSelector((state) =>
    state.product.products.find((product) => product._id === productId)
  );



 const [inputs, setInputs] = useState({
    title: "",
    desc: "",
    price: "",
    inStock: ""
  })
  const [file, setFile] = useState(null)
  const [cat, setCat] = useState([])
  const dispatch = useDispatch()

  const handleChange = (e) => {
    setInputs(prev => {
      return { ...prev, [e.target.name]: e.target.value };
    })
  }
  const handleCat = (e) => {
    setCat(e.target.value.split(","));
  }

  const handleClick = (e) => {
    e.preventDefault();
    
    const fileName = new Date().getTime() + file.name;
    const storage = getStorage(app)
    const StorageRef = ref(storage, fileName)
    const uploadTask = uploadBytesResumable(StorageRef, file);


    uploadTask.on('state_changed',
      (snapshot) => {

        const progress = (snapshot.bytesTransferred / snapshot.totalBytes) * 100;
        console.log('Upload is ' + progress + '% done');
        switch (snapshot.state) {
          case 'paused':
            console.log('Upload is paused');
            break;
          case 'running':
            console.log('Upload is running');
            break;
          default:
        }
      },
      (error) => {
        
      },
      () => {

        getDownloadURL(uploadTask.snapshot.ref).then((downloadURL) => {
          const product = { ...inputs, img: downloadURL, categories: cat };
          updateProduct(productId, product, dispatch)
        });

      }
    );


  }



return (
    <div className="product">
      <div className="productTitleContainer">
        <h1 className="productTitle">Product</h1>
        <Link to="/">
          <button className="productAddButton">Create</button>
        </Link>
      </div>
      <div className="productTop">
        <div className="productTopLeft">
          <Chart data={pStats} dataKey="Sales" title="Sales Performance" />
        </div>
        <div className="productTopRight">
          <div className="productInfoTop">
            <img src={product.img} alt="" className="productInfoImg" />
            <span className="productName">{product.title}</span>
          </div>
          <div className="productInfoBottom">
            <div className="productInfoItem">
              <span className="productInfoKey">id:</span>
              <span className="productInfoValue">{product._id}</span>
            </div>
            <div className="productInfoItem">
              <span className="productInfoKey">sales:</span>
              <span className="productInfoValue">5123</span>
            </div>
            <div className="productInfoItem">
              <span className="productInfoKey">in stock:</span>
              <span className="productInfoValue">{product.inStock}</span>
            </div>
          </div>
        </div>
      </div>
      <div className="productBottom">
        <form className="productForm">
          <div className="productFormLeft">
            <label>Product Name</label>
            <input name="title" type="text" placeholder={product.title} onChange={handleChange} />
            <label>Product Description</label>
            <input name="desc" type="text" placeholder={product.desc} onChange={handleChange} />
            <label>Price</label>
            <input name="price" type="text" placeholder={product.price} onChange={handleChange} />
            <label>Category</label>
            <input type="text" placeholder={product.categories} onChange={handleCat} />
            <label>In Stock</label>
            <select name="inStock" id="idStock" onChange={handleChange}>
              <option value="true">Yes</option>
              <option value="false">No</option>
            </select>
          </div>
          <div className="productFormRight">
            <div className="productUpload">
              <img src={product && product.img ? product.img : "https://pantaloons.imgix.net/img/app/product/3/391578-2035225.jpg?w=618&auto=format"} alt="" className="productUploadImg" />
              <label htmlFor="file">
                <Publish />
              </label>
              <input type="file" id="file" style={{ display: "none" }} onChange={e => setFile(e.target.files[0])} />
            </div>
            <button onClick={handleClick} className="productButton">Update</button>
          </div>
        </form>
      </div>
    </div>
  );
}

if I remove the image component where an error is showing, it again shows TypeError: Cannot read properties of undefined (reading 'title'). Why is this happening?

1 Answers

The app cannot find a product here:

const product = useSelector((state) =>
    state.product.products.find((product) => product._id === productId)
  );

I guess it could be because your productId is a string and _id is a number (in that case you should cast it to the same type). Or there is no such product in your state state.product.products at all.

Related