Reputation: 21
I am trying to fetch some data from api using redux for state management . I tried to dispatch the action from inside the useEffect but it does not work at all . I think there is some issue in dependencies but i cannot figure it out. I got the following error:
Cannot read properties of undefined (reading 'shippingAddress')
orderReducer.js
export const orderDetailsReducer = (
state = { loading: true, orderItems: [], shippingAddress: {} },
action
) => {
switch (action.type) {
case ORDER_DETAILS_REQUEST:
return { loading: true };
case ORDER_DETAILS_SUCCESS:
return { loading: false, order: action.payload };
case ORDER_DETAILS_FAIL:
return { loading: false, error: action.payload };
default:
return state;
}
};
orderAction.js
export const getOrderDetails = (id) => async (dispatch, getState) => {
try {
dispatch({
type: ORDER_DETAILS_REQUEST,
});
const {
loginuser: { userInfo },
} = getState();
const sdata = {
headers: {
"Content-type": "application/json",
Authorization: `Bearer ${userInfo.token}`,
},
};
const { data } = await axios.get(`/api/orders/${id}/`, sdata);
console.log("incoming data", data);
dispatch({
type: ORDER_DETAILS_SUCCESS,
payload: data,
});
} catch (error) {
dispatch({
type: ORDER_DETAILS_FAIL,
payload:
error.response && error.response.data.detail
? error.response.data.detail
: error.message,
});
}
};
store.js
import { createStore, combineReducers, applyMiddleware } from "redux";
import thunk from "redux-thunk";
import { composeWithDevTools } from "redux-devtools-extension";
import { productListReducer } from "./reducers/productReducers";
import { productDetailsReducer } from "./reducers/productReducers";
import { cartItemReducer } from "./reducers/cartReducers";
import {
userLoginReducer,
userRegisterReducer,
userDetailReducer,
useUpdateReducer,
} from "./reducers/userReducers";
import {
orderAddItemReducer,
orderDetailsReducer,
orderPayReducer,
} from "./reducers/orderReducers";
const reducer = combineReducers({
productList: productListReducer,
productDetails: productDetailsReducer,
cart: cartItemReducer,
loginuser: userLoginReducer,
registeruser: userRegisterReducer,
userDetails: userDetailReducer,
userUpdate: useUpdateReducer,
orderAddItem: orderAddItemReducer,
orderDetails: orderDetailsReducer,
orderPay: orderPayReducer,
});
const cartItemsInStorage = localStorage.getItem("cartItems")
? JSON.parse(localStorage.getItem("cartItems"))
: [];
const userInfoInStorage = localStorage.getItem("userInfo")
? JSON.parse(localStorage.getItem("userInfo"))
: null;
const shippingAddressInStorage = localStorage.getItem("shippingAddress")
? JSON.parse(localStorage.getItem("shippingAddress"))
: {};
console.log("itemsinstorage: ", cartItemsInStorage);
const initialState = {
cart: {
cartItems: cartItemsInStorage,
shippingAddress: shippingAddressInStorage,
},
loginuser: { userInfo: userInfoInStorage },
};
const middleware = [thunk];
const store = createStore(
reducer,
initialState,
composeWithDevTools(applyMiddleware(...middleware))
);
export default store;
OrderDetails.js
import React, { useEffect, useState } from "react";
import { getOrderDetails, payOrder } from "../actions/orderAction";
import { useNavigate, useParams } from "react-router";
import { useDispatch, useSelector } from "react-redux";
import { PayPalButtons } from "@paypal/react-paypal-js";
function OrderDetails() {
const { id } = useParams();
const dispatch = useDispatch();
const orderDetails = useSelector((state) => state.orderDetails);
const { order, error, loading } = orderDetails;
const orderPay = useSelector((state) => state.orderPay);
const { loading: loadingPay, success: successPay } = orderPay;
const { userInfo } = useSelector((state) => state.loginuser);
useEffect(() => {
if (!order) {
dispatch(getOrderDetails(id));
}
}, [id, order, dispatch]);
return (
<>
<div className="container">
<div className="row">
<div className="col-md-8 mt-5">
<ul className="list-group">
<li className="list-group-item p-2">
<h4 className="my-3">shipping</h4>
<span>
Address : {order.shippingAddress.address} ,{" "}
{order.shippingAddress.city} ,{" "}
{order.shippingAddress.postalcode} ,
{order.shippingAddress.country}{" "}
</span>
</li>
<li className="list-group-item p-2">
<h4 className="my-3">Payment Method</h4>
<span>{order.paymentMethos} </span>
</li>
<li className="list-group-item p-2">
<h4 className="my-3">ordered items</h4>
<ul className="list-group list-group-flush">
{order.orderItems.map((item) => (
<li className="list-group-item" key={item.product}>
<div className="row">
<div className="col-md-1">
<img
src={item.image}
alt={item.image}
className="img-fluid"
/>
</div>
<div className="col-md-7">
<strong>{item.name}</strong>
</div>
<div className="col-md-4">
<h6>
{" "}
{item.qty} x {item.price}
</h6>
</div>
</div>
</li>
))}
</ul>
</li>
</ul>
</div>
<div className="col-md-4 mt-5">
<ul className="list-group">
<li className="list-group-item pt-4 text-center">
<h5>PRICE SUMMARY</h5>
</li>
<li className="list-group-item p-3">
<div className="row">
<div className="col">item </div>
<div className="col">{order.itemsprice}</div>
</div>
</li>
<li className="list-group-item p-3">
<div className="row">
<div className="col">shipping</div>
<div className="col">{order.shippingprice}</div>
</div>
</li>
<li className="list-group-item p-3">
<div className="row">
<div className="col">tax </div>
<div className="col">{order.taxprice} </div>
</div>
</li>
<li className="list-group-item p-3">
<div className="row">
<div className="col">total </div>
<div className="col">{order.totalprice} </div>
</div>
</li>
</ul>
</div>
</div>
</div>
</>
);
}
export default OrderDetails;
Upvotes: 1
Views: 54
Reputation: 117
The issue is that the app crashes before having time to execute the useEffect hook. In your return
statement you have
Address : {order.shippingAddress.address} ,{" "}
{order.shippingAddress.city} ,{" "}
{order.shippingAddress.postalcode} ,
{order.shippingAddress.country}{" "}
But for the first render, the order
item is undefined
so it crashes. You should add some conditional check to only use orders when you know it's not undefined.
Upvotes: 1