MERN栈单个订单详情页面TypeError问题求助:无法解构undefined的order对象的paymentInfo属性
Hey there! Let's break down why this error is happening and how to fix it quickly. The root issue is that when your component first renders, the order state from Redux is still undefined—your API call to fetch the single order is asynchronous, so it takes a moment to load the data. Trying to destructure properties like paymentInfo from an undefined value throws that TypeError.
Here are the key fixes you need to implement:
1. Add Loading & Error State Checks
First, we should prevent rendering any order-dependent content until the data has finished loading, and handle errors if the API call fails. Add these checks right at the start of your component's return statement:
// Show loading state while fetching data if (loading) { return <div className="loading">Loading order details...</div>; } // Show error message if something goes wrong if (error) { return <div className="error">Oops! {error}</div>; }
This ensures we don't try to access order properties before they exist, and gives users clear feedback during loading/errors.
2. Use Default Values for Destructuring
Modify your Redux selector to give order a default empty object. This prevents the initial destructuring from failing when order is undefined:
const { loading, error, order = {} } = useSelector(state => state.myOrderDetails); const { paymentInfo, deliveryInfo, orderStatus, userID, itemsPrice, user, totPrice, orderItems, createdAt, customerName } = order;
Now even if order is undefined initially, we'll destructure from an empty object instead, avoiding the TypeError.
3. Fix Typos & Add Optional Chaining
I spotted a couple of typos and places where you should use optional chaining (?.) to safely access nested properties without breaking the app:
- You wrote
deliveryInfo && deliveryInfo.deliverStatuss(extra 's' at the end ofdeliverStatuss)—fix this todeliveryInfo?.deliverStatus - Replace direct access like
order.orderStatuswithorder?.orderStatusto avoid errors iforderis ever undefined - Update other direct
orderproperty accesses (likeorder._id,order.customerName) to use?.
Here's an example of corrected code snippets:
// Payment Status display <p className={String(paymentInfo?.paymentStatus).includes('Paid') ? " statustxt211 green211" : "statustxt211 red211" }> {paymentInfo?.paymentStatus} </p> // Delivery Status display <p className={String(deliveryInfo?.deliverStatus).includes('Delivered') ? " statustxt211 green211" : String(deliveryInfo?.deliverStatus).includes('Delivering') ? " statustxt211 orange211" : "statustxt211 red211" }> {deliveryInfo?.deliverStatus} </p> // Order ID display <h2 className="orderID">{order?._id}</h2>
4. Quick Sanity Check for Redux Flow
Your action code looks correct, but double-check your Redux reducer to ensure:
ORDER_DETAILS_REQUESTinitializesorderasnullorundefinedORDER_DETAILS_SUCCESScorrectly sets theorderpayload from the API response
This ensures data flows properly from your backend to the Redux store.
Full Modified Component Snippet (Key Sections)
Here's how your component will look with all fixes applied:
import { useDispatch, useSelector, useEffect, Fragment } from 'react-redux' import { getSingleOrder, clearErrors } from '../../../actions/orderActions' import './UserSingleOrderCard.css' const USOCard = ({ match }) => { const dispatch = useDispatch(); const { loading, error, order = {} } = useSelector(state => state.myOrderDetails) const { paymentInfo, deliveryInfo, orderStatus, userID, itemsPrice, user, totPrice, orderItems, createdAt, customerName } = order; useEffect(() => { dispatch(getSingleOrder(match.params.id)); if(error){ dispatch(clearErrors()) } }, [dispatch, error, match.params.id]) // Loading state if (loading) { return <div>Loading order details...</div>; } // Error state if (error) { return <div>Oops! {error}</div>; } return ( <Fragment> <div className="USOCCont211"> <h1 className="orderIDtxt">Order Id</h1> <h2 className="orderID">{order?._id}</h2> {/* Rest of your JSX with optional chaining fixes */} <div className="statsCont211"> <div className="statusCard"> <div className="statustxtdiv211"> <p className="ststxt">Payment Status</p><br/> <p className={String(paymentInfo?.paymentStatus).includes('Paid') ? " statustxt211 green211" : "statustxt211 red211" }>{paymentInfo?.paymentStatus}</p><br/> <button className={String(paymentInfo?.paymentStatus).includes('Paid') ? "btn211 disabled" : "btn211" }>Pay</button> </div> <div className="stsimgcont211"><img className="stsimg211" src="./images/uovPayment.png" /></div> </div> {/* Rest of your component code */} </div> </div> </Fragment> ) } export default USOCard
These changes will ensure your component handles asynchronous data loading gracefully, avoids the TypeError, and renders correctly once the order data is available.
内容的提问来源于stack exchange,提问作者Sandeepa Ishara

