简体   繁体   中英

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

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')

Hi there am having 2 ideas that might help:

  1. 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);
        }
      }; 
  1. 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!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM