redux - 장바구니 상품 추가

이윤희·2025년 2월 3일

React/Next 일기

목록 보기
37/52

구현 된거 : + 버튼 누르면 해당 id를 가진 상품의 count 를 1 증가

현재 목표 :

Detail 페이지에서 주문하기버튼 누르면,
Cart에 해당 상품이 있으면 수량을 +1 하기
아니면 해당 상품을 추가하기

임의로 데이터를 넣어서 테스트해봤는데 이렇게 공백으로 뜬다.

뭐가문젠가... GPT한테 물어봤다.

data.js

let data = [
  {
    id: 0,
    title: "White and Black",
    content: "Born in France",
    price: 120000,
    img: "https://codingapple1.github.io/shop/shoes1.jpg",
  },
... (똑같이생긴거 들어감. 생략)
];
export default data;

Detail.js

function Detail(props) {
  let cartState = useSelector((state) => state);
  let dispatch = useDispatch();
  let foundProduct = props.shoes.find((product) => {
    return product.id === parseInt(id);
  });
return foundProduct ? (
    <div className={"container black "+ fade2}>
      <div className="row">
        <div className="col-md-6">
          <img
            src="https://codingapple1.github.io/shop/shoes1.jpg"
            width="100%"
          />
        </div>
        <div className="col-md-6">
          <h4 className="pt-5">{foundProduct.title}</h4>
          <p>{foundProduct.content}</p>
          <p>{foundProduct.price}{stock}</p>
          <button className="btn btn-danger"
          onClick={()=>{
            dispatch(addToCart(foundProduct));
          }}
          >주문하기</button>
        </div>
      </div>
    </div>
  ) : (
    <div>상품을 찾을 수 없습니다.</div>
  );
}

store.js

import { configureStore, createSlice } from "@reduxjs/toolkit";
import { user, cart } from "./store/userSlice.js";
let stock = createSlice({
  name: "stock",
  initialState: [10, 11, 12],
});
export default configureStore({
  reducer: {
    user: user.reducer,
    stock: stock.reducer,
    cart: cart.reducer,
  },
});

userSlice.js

let cart = createSlice({
  name: "cart",
  initialState: [
    { id: 0, name: "White and Black", count: 2 },
    { id: 2, name: "Grey Yordan", count: 1 },
  ],
  reducers: {
    increaseCount(state, action) {
      let idx = state.findIndex( (item ) => item.id === action.payload);
      if(idx !== -1){
        state[idx].count += 1;
      }
    },
    addToCart(state,action){
      let newData =   {
        id: 0,
        title: "White and Black",
        content: "Born in France",
        price: 120000,
        img: "https://codingapple1.github.io/shop/shoes1.jpg",
      };
      let isNewOne = state.findIndex((item) => item.id === action.payload );
            if(isNewOne !== -1){
              state[isNewOne].count += 1;
            } else{
              state.push(newData);
            }
    }
  }
});

콘솔 찍어보니 데이터가 추가되기는 하는데, 화면에 데이터가 제대로 표시가 안된다.
이게 왜그런가,,, 했는데
생긴 게 다른 데이터를 집어넣어서 그렇다고.

GPT

newData를 직접 추가했는데 공백이 나오는 이유 🔍

현재 addToCart 리듀서에서 newData를 하드코딩하여 추가했지만, 공백이 나오는 이유는 Redux Toolkit의 Immer 동작 방식과 newData의 구조 문제 때문입니다.

🚨 현재 코드의 문제점

addToCart(state, action) {
  let newData = {
    id: 0,
    title: "White and Black",
    content: "Born in France",
    price: 120000,
    img: "https://codingapple1.github.io/shop/shoes1.jpg",
  };
  
  let isNewOne = state.findIndex((item) => item.id === action.payload);
  if (isNewOne !== -1) {
    state[isNewOne].count += 1;
  } else {
    state.push(newData);
  }
}

🛑 이 코드의 문제점:

  1. action.payloadfoundProduct 객체인데, findIndex에서 잘못된 비교 연산을 하고 있음.
    • state.findIndex((item) => item.id === action.payload)action.payload.id가 아니라 action.payload 자체를 비교하고 있음.
    • 따라서, 항상 isNewOne === -1이 되어 항상 새로운 데이터를 추가하게 됨.
  2. newData의 구조가 cart의 초기 상태 구조와 다름
    • cart의 초기 상태에는 { id, name, count }만 있음.
    • 하지만 newData{ id, title, content, price, img }를 포함하고 있음.
    • 그래서 Detail.js에서 cart.map((item) => <td>{item.name}</td>)처럼 name을 렌더링하려고 하면 undefined가 되어 공백으로 표시됨.

올바른 해결 방법

1️⃣ findIndex 비교 연산 수정

  • action.payload.id를 비교해야 함.
  • 기존 stateid 값과 action.payload.id를 비교해야 findIndex가 정상 동작함.

2️⃣ newDatacart 구조에 맞게 변환

  • cart의 데이터 구조 { id, name, count }에 맞춰 추가해야 정상적으로 렌더링됨.

🔥 수정된 코드

addToCart(state, action) {
  let isNewOne = state.findIndex((item) => item.id === action.payload.id);

  if (isNewOne !== -1) {
    state[isNewOne].count += 1;
  } else {
    state.push({
      id: action.payload.id,
      name: action.payload.title,  // 기존 title → name으로 변경
      count: 1
    });
  }
}

🔍 이제 어떻게 동작하는가?

✅ 장바구니에서 같은 상품이 있으면 count만 증가
✅ 장바구니에 상품이 없으면 { id, name, count } 형태로 추가
Detail.js에서 item.name을 렌더링할 때 정상적으로 표시됨
✅ 공백 문제 해결 🎉

이제 다시 실행해 보면, 장바구니에 정상적으로 제품이 추가될 것입니다! 🚀

0개의 댓글