온라인 강의/React 완벽 가이드 [Udemy]

157. 아이템을 이동식으로 만들기

유호야 2023. 6. 22. 23:43
반응형

 

약간 코드 따라치기를 하게 된 것 같기는 한데 ..

 중간 중간 생긴 에러들 잘 수정했다 

action id 대신 item을 비교해야 하는 경우들이 꽤 있었다.

 

Cart.js

import React, { useContext } from 'react';
import styles from './Cart.module.css';
import Modal from '../UI/Modal';
import CartContext from '../../store/cart-context';
import CartItem from './CartItem';

const Cart = props => {
  const cartCtx = useContext(CartContext);

  const totalAmount = `$${cartCtx.totalAmount.toFixed(2)}`;
  const hasItems = cartCtx.items.length > 0;
  const cartItemRemoveHandler = (id) => {
    cartCtx.removeItem(id);
  }
  const cartItemAddHandler = (item) => {
    cartCtx.addItem({ ...item, amount: 1 });
  }


  const cartItems = <ul className={styles['cart-items']}>
    {cartCtx.items.map((item) =>
      <CartItem key={item.id} name={item.name} amount={item.amount} price={item.price}
        onRemove={cartItemRemoveHandler.bind(null, item.id)}
        onAdd={cartItemAddHandler.bind(null, item)} />
    )}
  </ul>;

  return <Modal onClose={props.onClose}>
    {cartItems}
    <div className={styles.total}>
      <span>Total Amount</span>
      <span>{totalAmount}</span>
    </div>
    <div className={styles.actions}>
      <button className={styles['button--alt']} onClick={props.onClose}>Close</button>
      {hasItems &&
        <button className={styles.button}>Order</button>
      }
    </div>
  </Modal>
}

export default Cart;

CartProvider.js

import CartContext from './cart-context';
import { useReducer } from 'react';

const defaultCartState = {
  items: [],
  totalAmount: 0
}
const cartReducer = (state, action) => {
  if (action.type === 'ADD') {
    const exisitingCartItemIndex = state.items.findIndex(item => item.id === action.item.id);
    const exisitingCartItem = state.items[exisitingCartItemIndex];
    let updatedItem;

    let updatedItems = state.items.concat(action.item);
    if (exisitingCartItem) {
      updatedItem = {
        ...exisitingCartItem,
        amount: exisitingCartItem.amount + action.item.amount
      };
      updatedItems = [...state.items];
      updatedItems[exisitingCartItemIndex] = updatedItem;
    } else {
      updatedItems = state.items.concat(action.item);
    }

    const updatedTotalAmount = state.totalAmount + action.item.price * action.item.amount;
    return {
      items: updatedItems,
      totalAmount: updatedTotalAmount
    }

  } else if (action.type === 'REMOVE') {
    console.log('something');
    const existingCartItemIndex = state.items.findIndex(item => item.id === action.item);
    const existingItem = state.items[existingCartItemIndex];
    const updatedTotalAmount = state.totalAmount - existingItem.price;

    let updatedItems;
    if (existingItem.amount === 1) {
      console.log('this');
      console.log(action.item);
      updatedItems = state.items.filter(item => item.id !== action.item);
    } else {
      const updatedItem = { ...existingItem, amount: existingItem.amount - 1 };
      updatedItems = [...state.items];
      updatedItems[existingCartItemIndex] = updatedItem;
    }

    return {
      items: updatedItems,
      totalAmount: updatedTotalAmount
    };
  }

  return defaultCartState;
}

const CartProvider = props => {
  const [cartState, dispatchCartAction] = useReducer(cartReducer, defaultCartState);

  const addItemToCartHandler = item => {
    dispatchCartAction({ type: 'ADD', item: item });
  };

  const removeItemFromCartHandler = id => {
    dispatchCartAction({ type: 'REMOVE', item: id });
  };

  const cartContext = {
    items: cartState.items,
    totalAmount: cartState.totalAmount,
    addItem: addItemToCartHandler,
    removeItem: removeItemFromCartHandler
  };

  return <CartContext.Provider value={cartContext}>
    {props.children}
  </CartContext.Provider>
}

export default CartProvider;
반응형