when a user click the place order button i want to redirect the page to the order page showing user id in the url. navigate(/order/${data.order._id}
). but instead getting the following error in console TypeError: Cannot read properties of undefined (reading 'order')
. but the order is created with 201 status code as expected. when i check the database orders collection the order is placed with the id.
placeorderScreen.jsx in frontend
const reducer = (state, action) => {
switch (action.type) {
case 'Create_Request':
return { ...state, loading: true };
case 'Create_Success':
return { ...state, loading: false };
case 'Create_Fail':
return { ...state, loading: false };
default:
return state;
}
};
function PlaceOrderScreen() {
const navigate = useNavigate();
const [{ loading }, dispatch] = useReducer(reducer, {
loading: false,
});
const { state, dispatch: ctxDispatch } = useContext(Store);
const { cart, userInfo } = state;
const round2 = num => Math.round(num * 100 Number.EPSILON) / 100; // 123.2345 => 123.23
cart.itemsPrice = round2(
cart.cartItems.reduce((a, c) => a c.quantity * c.price, 0)
);
cart.shippingPrice = cart.itemsPrice > 100 ? round2(0) : round2(40);
cart.taxPrice = round2(0.15 * cart.itemsPrice);
cart.totalPrice = cart.itemsPrice cart.shippingPrice cart.taxPrice;
const placeOrderHandler = async () => {
try {
dispatch({ type: 'Create_Request' });
const { data } = axios.post(
'/api/orders',
{
orderItems: cart.cartItems,
shippingAddress: cart.shippingAddress,
paymentMethod: cart.paymentMethod,
itemsPrice: cart.itemsPrice,
shippingPrice: cart.shippingPrice,
taxPrice: cart.taxPrice,
totalPrice: cart.totalPrice,
},
{
headers: {
authorization: `Bearer ${userInfo.token}`,
},
}
);
ctxDispatch({type: 'Cart_Clear'});
dispatch({type: 'Create_Success'});
localStorage.removeItem('cartItems');
navigate(`/order/${data.order._id}`)
} catch (err) {
dispatch({ type: 'Create_Fail' });
toast.error(getError(err));
console.log(err);
}
};
the issue is occuring somewhere here
navigate(`/order/${data.order._id}`)
orderRoutes.js backend
import express from 'express';
import Order from '../models/orderModel.js';
import expressAsyncHandler from 'express-async-handler';
import { isAuth } from '../utils.js';
const orderRouter = express.Router();
orderRouter.post('/',isAuth, expressAsyncHandler(async(req,res) => {
const newOrder = new Order({
orderItems: req.body.orderItems.map((x) => ({...x, product: x._id})),
shippingAddress: req.body.shippingAddress,
paymentMethod: req.body.paymentMethod,
itemsPrice: req.body.itemsPrice,
shippingPrice: req.body.shippingPrice,
taxPrice: req.body.taxPrice,
totalPrice: req.body.totalPrice,
user: req.user._id,
})
const order = await newOrder.save();
res.status(201).send({message: 'New Order Created', order});
}))
export default orderRouter;
orderModel.js model schema
import mongoose from 'mongoose';
const orderSchema = new mongoose.Schema(
{
orderItems: [
{
slug: {type:String, required: true},
name: {type: String, required: true},
quantity: {type: Number, required: true},
image: {type:String, required: true},
price: {type: Number, required: true},
product: {
type: mongoose.Schema.Types.ObjectId,
ref: 'Product',
required: true,
}
}
],
shippingAddress: {
fullName: {type: String, required: true},
address: {type:String, required: true},
city: {type: String, required: true},
postalCode: {type: String, required: true},
country: {type: String, required: true},
},
paymentMethod: {type: String, required: true},
paymentResult: {
id: String,
status: String,
update_time: String,
email_address: String,
},
itemsPrice: {type: Number, required: true},
shippingPrice: {type: Number, required: true},
taxPrice: {type: Number, required: true},
totalPrice: {type: Number, required: true},
user: {type: mongoose.Schema.Types.ObjectId, ref: "User", required: true},
isPaid: {type: Boolean, default: false},
paidAt: {type: Date},
isDelivered: {type:Boolean, default: false},
deliveredAt: {type:Date}
},
{
timestamps: true
}
)
const Order = mongoose.model('Order', orderSchema);
export default Order;
error in console
TypeError: Cannot read properties of undefined (reading 'order')
CodePudding user response:
Hi there am having 2 ideas that might help:
- Inside your async "placeOrder" function put an "await" before your navigate() call. Maybe the data you excerpt is not available by the time your function executes.
const placeOrderHandler = async () => {
try {
dispatch({ type: 'Create_Request' });
const { data } = axios.post(
'/api/orders',
{
orderItems: cart.cartItems,
shippingAddress: cart.shippingAddress,
paymentMethod: cart.paymentMethod,
itemsPrice: cart.itemsPrice,
shippingPrice: cart.shippingPrice,
taxPrice: cart.taxPrice,
totalPrice: cart.totalPrice,
},
{
headers: {
authorization: `Bearer ${userInfo.token}`,
},
}
);
ctxDispatch({type: 'Cart_Clear'});
dispatch({type: 'Create_Success'});
localStorage.removeItem('cartItems');
await navigate(`/order/${data.order._id}`) <-- await keyword added
} catch (err) {
dispatch({ type: 'Create_Fail' });
toast.error(getError(err));
console.log(err);
}
};
- Check the data object that you return from the backend code, i would always return it with json format like this:
orderRouter.post('/',isAuth, expressAsyncHandler(async(req,res) => {
const newOrder = new Order({
orderItems: req.body.orderItems.map((x) => ({...x, product: x._id})),
shippingAddress: req.body.shippingAddress,
paymentMethod: req.body.paymentMethod,
itemsPrice: req.body.itemsPrice,
shippingPrice: req.body.shippingPrice,
taxPrice: req.body.taxPrice,
totalPrice: req.body.totalPrice,
user: req.user._id,
})
const order = await newOrder.save();
res.status(201).json({status: 'Success', order}); <-- changed response
Hope this is helping!