Home > Mobile >  Unable to add property in object
Unable to add property in object

Time:10-23

I am following a tutorial. I am adding itemsPrice, shippingPrice, taxPrice, totalPrice in cart object in PlaceOrderScreen.js in same way as the instructor is doing it but his code is working fine but my code gives this error "TypeError: Cannot add property itemsPrice, object is not extensible".

PlaceOrderScreen.js

import React, { useState } from 'react';
import { Link } from 'react-router-dom';

import {
  Button,
  Row,
  Col,
  ListGroup,
  Image,
  Card,
  ListGroupItem,
} from 'react-bootstrap';
import { useDispatch, useSelector } from 'react-redux';
import Message from '../components/Message';
import CheckoutSteps from '../components/CheckoutSteps';
import { createOrder } from '../features/OrderFeature/orderSlice';

const PlaceOrderScreen = () => {
  const dispatch = useDispatch();
  const cart = useSelector((store) => store.cart);
  //Calculate Prices
  const addDecimals = (num) => {
    return (Math.round(num * 100) / 100).toFixed(2);
  };
  cart.itemsPrice = addDecimals(
    cart.cartItems.reduce((acc, item) => acc   item.price * item.qty, 0)
  );
  cart.shippingPrice = addDecimals(cart.itemsPrice > 100 ? 0 : 100);
  cart.taxPrice = addDecimals(Number((0.15 * cart.itemsPrice).toFixed(2)));
  cart.totalPrice = (
    Number(cart.itemsPrice)  
    Number(cart.shippingPrice)  
    Number(cart.taxPrice)
  ).toFixed(2);

  const placeOrderHandler = () => {
    console.log('Order placed');
    // dispatch(
    //   createOrder({
    //     orderItems: cart.cartItems,
    //     shippingAddress: cart.shippingAddress,
    //     paymentMethod: cart.paymentMethod,
    //   })
    // );
  };
  return (
    <>
      <CheckoutSteps step1 step2 step3 step4 />
      <Row>
        <Col md={8}>
          <ListGroup variant='flush'>
            <ListGroup.Item>
              <h2>Shipping</h2>
              <p>
                <strong>Address:</strong>
                {cart.shippingAddress.address},{cart.shippingAddress.city},
                {cart.shippingAddress.postalCode},{cart.shippingAddress.country}
                ,
              </p>
            </ListGroup.Item>
            <ListGroup.Item>
              <h2>Payment Method</h2>
              <strong>Method:</strong>
              {cart.paymentMethod}
            </ListGroup.Item>

            <ListGroup.Item>
              <h2>Order Items</h2>
              {cart.cartItems.length === 0 ? (
                <Message>Your Cart is empty</Message>
              ) : (
                <ListGroup variant='flush'>
                  {cart.cartItems.map((item, index) => {
                    return (
                      <ListGroupItem key={index}>
                        <Row>
                          <Col md={1}>
                            <Image
                              src={item.image}
                              alt={item.name}
                              fluid
                              rounded
                            />
                          </Col>
                          <Col>
                            <Link to={`/product/${item.product}`}>
                              {item.name}
                            </Link>
                          </Col>

                          <Col md={4}>
                            {item.qty} x ${item.price}=${item.qty * item.price}
                          </Col>
                        </Row>
                      </ListGroupItem>
                    );
                  })}
                </ListGroup>
              )}
            </ListGroup.Item>
          </ListGroup>
        </Col>
        <Col md={4}>
          <Card>
            <ListGroup variant='flush'>
              <ListGroup.Item>
                <h2>Order Summary</h2>
              </ListGroup.Item>
              <ListGroup.Item>
                <Row>
                  <Col>Items</Col>
                  <Col>${cart.itemsPrice}</Col>
                </Row>
              </ListGroup.Item>
              <ListGroup.Item>
                <Row>
                  <Col>Shipping</Col>
                  <Col>${cart.shippingPrice}</Col>
                </Row>
              </ListGroup.Item>
              <ListGroup.Item>
                <Row>
                  <Col>Tax</Col>
                  <Col>${cart.taxPrice}</Col>
                </Row>
              </ListGroup.Item>
              <ListGroup.Item>
                <Row>
                  <Col>Total</Col>
                  <Col>${cart.totalPrice}</Col>
                </Row>
              </ListGroup.Item>
              <ListGroup.Item>
                <Button
                  type='button'
                  className='btn-block'
                  disabled={cart.cartItems === 0}
                  onClick={placeOrderHandler}
                >
                  Place Order
                </Button>
              </ListGroup.Item>
            </ListGroup>
          </Card>
        </Col>
      </Row>
    </>
  );
};

export default PlaceOrderScreen;

store.js

import { configureStore } from '@reduxjs/toolkit';
import productListReducer from './features/productListFeature/productListSlice';
import productDetailsReducer from './features/productListFeature/productDetailSlice';
import CartReducer from './features/addToCart/cartSlice';
import userLoginReducer from './features/UserFeature/loginUserSlice';
import userRegisterReducer from './features/UserFeature/registerUserSlice';
import userDetailsReducer from './features/UserFeature/userDetailsSlice';
import userUpdateProfileReducer from './features/UserFeature/updateProfileSlice';
import orderCreateReducer from './features/OrderFeature/orderSlice';

const cartItemsFromStorage = localStorage.getItem('cartItems')
  ? JSON.parse(localStorage.getItem('cartItems'))
  : [];

const userInfoFromStorage = localStorage.getItem('userInfo')
  ? JSON.parse(localStorage.getItem('userInfo'))
  : null; //agr user info ni available to null return kar do
const shippingAddressFromStorage = localStorage.getItem('shippingAddress')
  ? JSON.parse(localStorage.getItem('shippingAddress'))
  : {};

const initialState = {
  cart: {
    cartItems: cartItemsFromStorage,
    shippingAddress: shippingAddressFromStorage,
  },
  userLogin: {
    userInfo: userInfoFromStorage,
  },
};

const store = configureStore({
  reducer: {
    productList: productListReducer,
    productDetails: productDetailsReducer,
    cart: CartReducer,
    userLogin: userLoginReducer,
    userRegister: userRegisterReducer,
    userDetails: userDetailsReducer,
    userUpdateProfile: userUpdateProfileReducer,
    orderCreate: orderCreateReducer,
  },
  preloadedState: initialState, 
});
export default store;

CodePudding user response:

You cannot modify the store value that way, you need to make a copy of it, save it to state. Eg.

const [modifiedCart, setModifiedCart] = useState(null);

useEffect(() => {
 const cartObject = {...cart};

 cartObject.itemsPrice = addDecimals(
  cartObject.cartItems.reduce((acc, item) => acc   item.price * item.qty, 0)
 );
 cartObject.shippingPrice = addDecimals(cartObject.itemsPrice > 100 ? 0 : 100);
 cartObject.taxPrice = addDecimals(Number((0.15 * cartObject.itemsPrice).toFixed(2)));
 cartObject.totalPrice = (
  Number(cartObject.itemsPrice)  
  Number(cartObject.shippingPrice)  
  Number(cartObject.taxPrice)
 ).toFixed(2);
 setModifiedCart(cartObject)
}, [cart])

and below in your JSX return replace cart with modifiedCart.

Hope that helps

  • Related