When trying to send request via axios to backend(mongodb) , throws validation error. and this only happens while trying to create product via front-end. i tried creating product via Postman and it works fine.
Addproductpage
import { React, useEffect, useState } from "react";
import CustomInput from "../components/CustomInput";
import ReactQuill from "react-quill";
import { useNavigate } from "react-router-dom";
import "react-quill/dist/quill.snow.css";
import { toast } from "react-toastify";
import * as yup from "yup";
import { useFormik } from "formik";
import { useDispatch, useSelector } from "react-redux";
import { getBrands } from "../features/brand/brandSlice";
import { getPCategory } from "../features/pCategory/pCategorySlice";
import { getColors } from "../features/color/colorSlice";
import { Select } from "antd";
import Dropzone from "react-dropzone";
import { delImg, uploadImg } from "../features/upload/uploadSlice";
import { createProducts, resetState } from "../features/product/productSlice";
let schema = yup.object().shape({
title: yup.string().required("Title is Required"),
description: yup.string().required("Description is Required"),
price: yup.number().required("Price is Required"),
brand: yup.string().required("Brand is Required"),
category: yup.string().required("Category is Required"),
tags: yup.string().required("Tag is Required"),
color: yup
.array()
.min(1, "Pick at least one color")
.required("Color is Required"),
quantity: yup.number().required("Quantity is Required"),
});
const Addproduct = () => {
const dispatch = useDispatch();
const navigate = useNavigate();
const [color, setColor] = useState([]);
const [images, setImages] = useState([]);
console.log(color);
useEffect(() => {
dispatch(getBrands());
dispatch(getPCategory());
dispatch(getColors());
}, []);
const brandState = useSelector((state) => state.brands.brands);
const catState = useSelector((state) => state.productCategories.productCategory);
const colorState = useSelector((state) => state.colors.colors);
const imgState = useSelector((state) => state.upload.images);
const newProduct = useSelector((state) => state.products.products);
const { isSuccess, isError, isLoading, createdProduct } = newProduct;
useEffect(() => {
if (isSuccess && createdProduct) {
toast.success("Product Added Successfullly!");
}
if (isError) {
toast.error("Something Went Wrong!");
}
}, [isSuccess, isError, isLoading]);
const coloropt = [];
colorState.forEach((i) => {
coloropt.push({
label: i.title,
value: i._id,
});
});
const img = [];
imgState.forEach((i) => {
img.push({
public_id: i.public_id,
url: i.url,
});
});
useEffect(() => {
formik.values.color = color ? color : " ";
formik.values.images = img;
}, [color, img]);
const formik = useFormik({
initialValues: {
title:"",
description:"",
price:"",
brand:"",
category:"",
tags:"",
color:"",
quantity:"",
images:"",
},
validationSchema: schema,
onSubmit: (values) => {
alert(JSON.stringify(values));
dispatch(createProducts(values));
formik.resetForm();
setColor(null);
setTimeout(() => {
dispatch(resetState());
}, 3000);
},
});
const handleColors = (e) => {
setColor(e);
console.log(color);
};
return (
<div>
<h3 className="mb-4 title">Add Product</h3>
<div>
<form
onSubmit={formik.handleSubmit}
className="d-flex gap-3 flex-column"
>
<CustomInput
type="text"
label="Enter Product Title"
name="title"
onCh={formik.handleChange("title")}
onBlr={formik.handleBlur("title")}
val={formik.values.title}
/>
<div className="error">
{formik.touched.title && formik.errors.title}
</div>
<div className="">
<ReactQuill
theme="snow"
name="description"
onChange={formik.handleChange("description")}
value={formik.values.description}
/>
</div>
<div className="error">
{formik.touched.description && formik.errors.description}
</div>
<CustomInput
type="number"
label="Enter Product Price"
name="price"
onCh={formik.handleChange("price")}
onBlr={formik.handleBlur("price")}
val={formik.values.price}
/>
<div className="error">
{formik.touched.price && formik.errors.price}
</div>
<select
name="brand"
onChange={formik.handleChange("brand")}
onBlur={formik.handleBlur("brand")}
value={formik.values.brand}
className="form-control py-3 mb-3"
id=""
>
<option value="">Select Brand</option>
{brandState.map((i, j) => {
return (
<option key={j} value={i.title}>
{i.title}
</option>
);
})}
</select>
<div className="error">
{formik.touched.brand && formik.errors.brand}
</div>
<select
name="category"
onChange={formik.handleChange("category")}
onBlur={formik.handleBlur("category")}
value={formik.values.category}
className="form-control py-3 mb-3"
id=""
>
<option value="">Select Category</option>
{catState.map((i, j) => {
return (
<option key={j} value={i.title}>
{i.title}
</option>
);
})}
</select>
<div className="error">
{formik.touched.category && formik.errors.category}
</div>
<select
name="tags"
onChange={formik.handleChange("tags")}
onBlur={formik.handleBlur("tags")}
value={formik.values.tags}
className="form-control py-3 mb-3"
id=""
>
<option value="" disabled>
Select Category
</option>
<option value="featured">Featured</option>
<option value="popular">Popular</option>
<option value="special">Special</option>
</select>
<div className="error">
{formik.touched.tags && formik.errors.tags}
</div>
<Select
mode="multiple"
allowClear
className="w-100"
placeholder="Select colors"
defaultValue={color}
onChange={(i) => handleColors(i)}
options={coloropt}
/>
<div className="error">
{formik.touched.color && formik.errors.color}
</div>
<CustomInput
type="number"
label="Enter Product Quantity"
name="quantity"
onCh={formik.handleChange("quantity")}
onBlr={formik.handleBlur("quantity")}
val={formik.values.quantity}
/>
<div className="error">
{formik.touched.quantity && formik.errors.quantity}
</div>
<div className="bg-white border-1 p-5 text-center">
<Dropzone
onDrop={(acceptedFiles) => dispatch(uploadImg(acceptedFiles))}
>
{({ getRootProps, getInputProps }) => (
<section>
<div {...getRootProps()}>
<input {...getInputProps()} />
<p>
Drag 'n' drop some files here, or click to select files
</p>
</div>
</section>
)}
</Dropzone>
</div>
<div className="showimages d-flex flex-wrap gap-3">
{imgState?.map((i, j) => {
return (
<div className=" position-relative" key={j}>
<button
type="button"
onClick={() => dispatch(delImg(i.public_id))}
className="btn-close position-absolute"
style={{ top: "10px", right: "10px" }}
></button>
<img src={i.url} alt="" width={200} height={200} />
</div>
);
})}
</div>
<button
className="btn btn-success border-0 rounded-3 my-5"
type="submit"
>
Add Product
</button>
</form>
</div>
</div>
);
};
export default Addproduct;
productService
import axios from "axios";
import config from "../../app/utils/axiosconfig";
const getProducts = async ()=>
{
const response = await axios.get('http://localhost:5000/api/products/allproduct');
return response.data;
}
const createProduct = async(product)=>{
console.log(product);
const response = await axios.post('http://localhost:5000/api/products/',product,config);
return response.data;
}
const productService ={
getProducts,
createProduct,
}
export default productService;
productslice
import { createSlice,createAsyncThunk, createAction } from "@reduxjs/toolkit";
import productService from "./productService";
const initialState ={
products: [],
isError: false,
isLoading:false,
isSuccess: false,
message: "",
}
export const getproducts = createAsyncThunk('product/get-products',async(thunkApi)=>{
try {
return await productService.getProducts();
} catch (error) {
return thunkApi.rejectWithValue(error);
}
});
export const createProducts = createAsyncThunk('Add/product',async(thunkApi,productData)=>{
try {
return await productService.createProduct(productData);
} catch (error) {
return thunkApi.rejectWithValue(error)
}
})
export const resetState = createAction("Reset_all");
export const productSlice = createSlice({
name: "products",
initialState,
reducers:{},
extraReducers:(builder)=>{
builder.addCase(getproducts.pending,
(state)=>{
state.isLoading = true;
}).addCase(getproducts.fulfilled,
(state,action)=>{
state.isLoading = false;
state.isSuccess = true;
state.products = action.payload;
}).addCase(getproducts.rejected,
(state,action)=>{
state.isLoading = false;
state.isError = true;
state.isSuccess = false;
state.message= action.error;
}).addCase(createProducts.pending,(state)=>{
state.isLoading=true;
}).addCase(createProducts.fulfilled,(state,action)=>{
state.isError=false;
state.isLoading=false;
state.isSuccess = true;
state.createdProduct = action.payload;
}).addCase(createProducts.rejected,(state,action)=>{
state.isError=true;
state.isLoading=false;
state.isSuccess = false;
state.message = action.error;}).addCase(resetState,()=> initialState);
},
})
export default productSlice.reducer;
the values from front end[the error]success in postman(https://i.stack.imgur.com/XCmuq.png)
I am trying to create a product,
product model
const mongoose = require("mongoose"); // Erase if already required
// Declare the Schema of the Mongo model
var productSchema = new mongoose.Schema(
{
title: {
type: String,
required: true,
trim: true,
},
slug: {
type: String,
required: true,
unique: true,
lowercase: true,
},
description: {
type: String,
required: true,
},
price: {
type: Number,
required: true,
},
category: {
type: String,
required: true,
},
brand: {
type: String,
required: true,
},
quantity: {
type: Number,
required: true,
},
sold: {
type: Number,
default: 0,
},
images: [
{
public_id: String,
url: String,
},
],
color: [],
tags: String,
ratings: [
{
star: Number,
comment: String,
postedby: { type: mongoose.Schema.Types.ObjectId, ref: "User" },
},
],
totalrating: {
type: String,
default: 0,
},
},
{ timestamps: true }
);
//Export the model
module.exports = mongoose.model("Product", productSchema);
product controller
const createProduct = asyncHandler(async (req, res) => {
try {
if (req.body.title) {
req.body.slug = slugify(req.body.title);
}
const newProduct = await Product.create(req.body);
res.json(newProduct);
} catch (error) {
throw new Error(error);
}
});
btw i’m new to web development,apologies for poor representation of the problem. thanks
