I have been trying to update product on my ecommerce website, when update button is clicked no errors are showing, its showing the old data and no change in the mongodb database.
when i print "req.body.name" in the controller code, it shows undefined in the console.
somebody please suggest a change in the code
Controller
import Product from "../models/productModel.js";
import Category from "../models/categoryModel.js"
import multer from "multer";
import productModel from "../models/productModel.js";
export const updateproducts = async (req, res) => {
try {
console.log("name "+req.body.name)
const product = await productModel.findByIdAndUpdate(
req.params.id,
{
name: req.body.name,
description: req.body.description,
images: req.body.images,
mrp: req.body.mrp,
category: req.body.category,
InStock: req.body.InStock,
rating: req.body.rating,
numReviews: req.body.numReviews,
isFeatured: req.body.isFeatured
},
{ new: true }
);
if (!product) {
return res.status(404).json({ error: 'Product not found or cannot be updated.' });
}
res.json({ message: 'Product updated successfully', updatedProduct: product });
} catch (error) {
console.error(error);
res.status(500).json({ error: 'Internal Server Error' });
}
};
frontend
import React, { useState, useEffect } from "react";
import AdminSidebar from '../../components/Layout/admin/adminSidebar'
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'
import { useNavigate, useParams } from "react-router-dom";
import toast from "react-hot-toast";
import axios from "axios";
import { faTrashCan } from '@fortawesome/free-solid-svg-icons';
import Form from 'react-bootstrap/Form';
import AdminHeader from '../../components/Layout/admin/adminheader'
import "./Admindashboard.css"
const UpdateProduct = () => {
const navigate = useNavigate();
const [categories, setCategories] = useState([]);
const [name, setName] = useState("");
const [description, setDescription] = useState("");
const [mrp, setMrp] = useState("");
const [category, setCategory] = useState("");
const params = useParams();
const [InStock, setInStock] = useState("");
const [selectedImages, setSelectedImages] = useState([]);
const [pid, setId] = useState("");
const [DeletedImages,setDeletedImages] = useState([])
const getSingleProduct = async () => {
try {
const { data } = await axios.get(`/api/v1/product/getsingle-product/${params.id}`);
console.log(data)
setName(data.product.name);
setId(data.product._id);
setDescription(data.product.description);
setSelectedImages(data.product.images);
setMrp(data.product.mrp);
setCategory(data.product.category);
setInStock(data.product.InStock);
if (data.success) {
console.log("hai")
}
} catch (error) {
console.log(error);
toast.error("Something wwent wrong in getting catgeory");
}
};
useEffect(() => {
getSingleProduct(params.id);
console.log(params.id)
//eslint-disable-next-line
}, []);
const getAllCategory = async () => {
try {
const { data } = await axios.get("/api/v1/category/get-category");
if (data.success) {
setCategories(data.category);
}
} catch (error) {
console.log(error);
toast.error("Something wwent wrong in getting catgeory");
}
};
useEffect(() => {
getAllCategory();
}, []);
//update product function
const handleUpdate = async (e) => {
e.preventDefault();
try {
const productData = new FormData();
productData.append("name", name);
productData.append("description", description);
for (let img of selectedImages) {
productData.append("images", img);
}
productData.append("mrp", mrp);
productData.append("category", category);
productData.append("InStock", InStock);
const { data } = await axios.put(`/api/v1/product/update-product/${params.id}`, {productData});
console.log(productData)
if (data?.success) {
toast.error(data?.message);
} else {
toast.success("Product Created Successfully");
navigate("/dashboard/manage.vision/admin/products");
}
} catch (error) {
console.log(error);
toast.error("something went wrong");
}
};
const onSelectFile = (event) => {
const selectedFiles = event.target.files;
const selectedFilesArray = Array.from(selectedFiles);
setSelectedImages((previousImages) => previousImages.concat(selectedFilesArray));
console.log(selectedImages)
// FOR BUG IN CHROME
event.target.value = "";
};
const deleteHandler = (file) => {
setDeletedImages((prevDeletedImages) => [...prevDeletedImages, file]);
const remainingImages = selectedImages.filter((f) => f !== file);
setSelectedImages(remainingImages);
};
return (
<body className='body'>
<div className="container-fluid ">
<div className="row">
<AdminHeader />
<AdminSidebar />
<div className="col-md-3">
<div>
<button>Cancel</button><button onClick={handleUpdate}>Update</button>
<div className="prgrid">
<div className='upimg'>
<h4 className="prhead">Product Images<hr></hr>
</h4>
<div >
<input type="file" id='upload' accept="image/png, image/jpeg,image/webp" onChange={onSelectFile} multiple >
</input><label className="label" for="upload"><h3 >Upload +</h3></label>
<div className="images">
{selectedImages &&
selectedImages.map((image, index) => {
return (
<div key={image} className="image">
<img src={`http://localhost:3000/uploads/${image}`} alt="upload" className="primg" />
<FontAwesomeIcon icon={faTrashCan} className="prdele" onClick={() => deleteHandler(image)} />
<p className="imgno">{index + 1}</p>
</div>
);
})}
</div>
</div>
</div>
<div className="prcat">
<h4 className="prhead">Product Catagory</h4><hr></hr>
<Form.Select className="catsel" onChange={(e) => setCategory(e.target.value)
}>{categories?.map((c) => (
<option key={c._id} value={c._id}>
{c.name}
</option>
))}
</Form.Select>
</div>
</div>
<div className="prinfo">
<h4 className="prhead">Product Info</h4><hr></hr>
<Form.Label htmlFor="prname" className="prlab">Name</Form.Label>
<Form.Control
type="text"
id="prname"
value={name}
placeholder="Product Name"
required
onChange={(e) => setName(e.target.value)}
/>
<Form.Group
className="mb-3"
controlId="exampleForm.ControlTextarea1"
>
<Form.Label className="prlab">Description</Form.Label>
<Form.Control as="textarea" rows={3} className="prdes" value={description} onChange={(e) => setDescription(e.target.value)} />
</Form.Group>
</div>
<div className="prprice">
<h4 className="prhead">Product Pricing</h4><hr></hr>
<Form.Label htmlFor="prpice" className="prlab">Maximum Retail Price</Form.Label>
<Form.Control
type="number"
id="prpice"
value={mrp}
onChange={(e) => setMrp(e.target.value)}
required
/>
</div>
<div className="prprice">
<h4 className="prhead">Inventory Status</h4><hr></hr>
<Form.Label htmlFor="prpice" className="prlab">Status</Form.Label>
<Form.Select aria-label="Default select example" className="stat" value={InStock} onChange={(e) => setInStock(e.target.value)}>
<option >Update Status</option>
<option value="0">In Stock</option>
<option value="1">Out Of Stock</option>
</Form.Select></div>
</div>
</div>
</div>
</div>
</body>
)
}
export default UpdateProduct
2
Answers
Are you sure to enter the required data inputs in the request ?
Can you share a snippet of how you use this controller endpoint on your frontend or from Postman for example ?
You’re not using correct request format with axios, meaning that instead of a form and multipart type request, you’re actually sending a JSON object here:
Try changing it to this (omit
{}
):docs: Multipart Bodies
Also, make sure you have multer middleware on that route, processing an array of files in
images
field, it should look something like this:docs: Usage