iamcoder
iamcoder

Reputation: 21

useEffect is not trigggering

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

Answers (1)

Jose Tomas
Jose Tomas

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

Related Questions