I'm creating a full stack MERN stack app, my front end is getting passed down the categories prop which is the model that i'm referencing to create a new Item, which is the model i'm trying to create on.
I'm getting a 400 error when I use the form to add new data. I'm new to the MERN stack so i'm not sure what exactly I'm missing when I send the data to my server. I'm guessing the issue is in my controller function, I just can not figure out how to add that reference on when I send the request to my server. Any help would be greatly appreciated
Error when I add an item, console logged the productData
Form component for adding Item
export default function AddProductForm({addProduct, categories}) {
const [newProduct, setNewProduct] = useState({
name: "",
images: [],
category: {categories},
price: 0,
description: ""
});
function handleChange (evt) {
setNewProduct({...newProduct, [evt.target.name]: evt.target.value });
}
async function handleAddProduct(evt) {
evt.preventDefault();
addProduct(newProduct);
setNewProduct({
name: "",
images: [],
category: {categories},
price: 0,
description: ""
});
}
return (
<>
<h1>Add New Product</h1>
<form onSubmit={handleAddProduct}>
<label>Name</label>
<input
name="name"
type="text"
value={newProduct.name}
onChange={handleChange}
required
/>
<label>images</label>
<input
name="images"
type="text"
value={newProduct.images}
onChange={handleChange}
required
/>
<label>category</label>
<select
name="category"
value={newProduct.category}
onChange={handleChange}>
{categories.map ((cat, idx) => (
<option key={idx} value={cat}>{cat}</option>
))}
</select>
<label>Price</label>
<input
name="price"
type="number"
value={newProduct.price}
onChange={handleChange}
required
/>
<label>Description</label>
<input
name="description"
type="text"
value={newProduct.description}
onChange={handleChange}
required
/>
<button type="submit">Add Product</button>
</form>
</>
);
}
Page where Form component lives
export default function AdminPage({categories}) {
const [allProducts, setAllProducts] = useState([]);
const [allOrders, setAllOrders] = useState([]);
useEffect(function() {
async function getProducts() {
const items = await itemsAPI.getAll();
setAllProducts(items);
}
getProducts();
async function getOrders() {
const orders = await ordersAPI.getAllActiveOrders();
setAllOrders(orders)
}
getOrders();
}, []);
async function updateOrder(orderData){
console.log(orderData)
const updatedOrder = await ordersAPI.updateOrder(orderData);
setAllOrders([...allOrders, updatedOrder]);
}
async function addProduct(productData) {
console.log(productData)
const newProduct = await itemsAPI.createItem(productData);
setAllProducts([...allProducts, newProduct]);
}
async function deleteProduct(itemId) {
const products = await itemsAPI.removeItem(itemId);
setAllProducts(products);
window.location.reload(false);
}
return (
<div className="admin-page">
<h1>Admin Page</h1>
<h2>All Available Products </h2>
<div className="admin-products">
{allProducts.map((product, idx) => (
<div key={idx}>{product.name}<br></br>
<img src={`${product.images[0]}`} alt=""/><br></br>
{/* <button>Edit</button> */}
<button onClick={() => deleteProduct(product._id)}>Delete Item</button>
</div>
))}
</div>
<AddProductForm addProduct={addProduct} categories={categories} />
<h1>ACTIVE ORDERS</h1>
<div className="orders">
{allOrders.map((order, idx) => (
<div key={idx} className="order-info">
Order ID: {order.orderId}<br></br>
Ordered on: {new Date(order.updatedAt).toLocaleDateString()}<br></br>
Order Total: ${order.orderTotal}
{order.shipment.map((info, idx) => (
<div key={idx} className="shipment-info">
<h3>Ship to:</h3>
<p>
{info.name}<br></br>
{info.address}<br></br>
{info.city},
{info.state}
{info.zip}
</p>
</div>
))}
<UpdateOrderForm updateOrder={updateOrder}/>
</div>
))}
</div>
</div>
);
}
Item model (what I'm trying to create a new instance of)
const Schema = require('mongoose').Schema;
const itemSchema = new Schema({
name: { type: String, required: true },
images: [{ type: String, required: true }],
category: {type: Schema.Types.ObjectId, ref: 'Category'},
price: { type: Number, required: true },
description: { type: String }
}, {
timestamps: true
});
module.exports = itemSchema;
category model (referenced model)
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const categorySchema = new Schema({
name: { type: String, required: true },
sortOrder: Number
}, {
timestamps: true
});
module.exports = mongoose.model('Category', categorySchema);
controller for creating item
async function create(req, res) {
try {
const item = await Item.create(req.body);
res.json(item);
} catch (err) {
res.status(400).json(err);
}
}
api call to route
export async function createItem(productData) {
return sendRequest(`${BASE_URL}/new`, 'POST', productData)
}