이번 과제도 과제 파일 자체를 이해하는 데 조금 오래 걸렸다.
다른 사람이 작성한 코드의 구조를 파악하는 건... 정말 어렵구나...🥹
이해한 바를 정리하기 위해서 일단 그림을 조금 그려봤다!
그냥 과제의 중심이 되는 Items나 Cartitems에만 집중했고 notification과 관련해서는 조금 대충 보고 적은 거라 정확하지 않을 수도 있다...!
: Object.assign으로 객체의 값을 복사할 수 있다. Redux의 state 업데이트는 immutable한 방식으로 변경해야 하므로 객체를 복사할 때 Object.assign을 이용할 수 있음.
const obj = { a: 1 };
const copy = Object.assign({}, obj);
console.log(copy); // { a: 1 }
reducer를 실행해 state 값을 변경할 경우 default value로 받아온 값을 온전히 대체하게 되기 때문에 직접적으로 변화를 주지 않는 부분들도 동일하게 받아와야한다.
예를 들어서 itemReducer 내부에서 switch를 통해 case를 나누어주었는데, 그 중 REMOVE_FROM_CART에 해당하는 타입일 때는 삭제 버튼이 눌린 아이템의 id값에 해당하는 cartItems의 요소만 삭제되어야 하는데, filter를 통해서 그 id를 가진 아이템만 제외한 배열을 만들었다고 할 지라도, Object.assign을 통해서 원래 initialState에 존재하던 값들을 우선 다 복사해오고, 바뀐 cartItems 키 부분에 해당하는 값만 추가해서 바뀐 객체를 리턴해주어야 한다.
case REMOVE_FROM_CART:
return Object.assign({}, state, {
cartItems: state.cartItems.filter(
(el) => el.itemId !== action.payload.itemId
),
});
break;
SET_QUANTITY 타입일 때, map을 통해 순회하지 않고도 slice나 spread 연산자를 통해서 상태를 변경해줄 수 있다. (과제에서 이미 idx라는, 수량이 변경될 아이템의 index를 구해놓고 있기 때문에 가능)
//map 이용
case SET_QUANTITY:
let idx = state.cartItems.findIndex(
(el) => el.itemId === action.payload.itemId
);
return Object.assign({}, state, {
cartItems: [
...state.cartItems.map((el, index) =>
index === idx
? { itemId: el.itemId, quantity: action.payload.quantity }
: el
),
],
});
break;
//spread 연산자 사용
case SET_QUANTITY:
let idx = state.cartItems.findIndex(
(el) => el.itemId === action.payload.itemId
);
let clone = {...state}
clone.cartItems[idx].quantity = action.payload.quantity;
return clone;
break;
//slice 사용
case SET_QUANTITY:
let idx = state.cartItems.findIndex(
(el) => el.itemId === action.payload.itemId
);
return Object.assign({}, state, {
cartItems: [
...state.cartItems.slice(0, idx),
{ itemId: action.payload.itemId, quantity: action.payload.quantity },
...state.cartItems.slice(idx + 1),
],
});
break;
default:
return state;