👉 오늘은 리덕트를 이용해 상태 관리를 하다가,
reducer 함수를 작성하며 객체를 합쳐야 할 필요가 있었다.
이때 Object.assign() 함수를 사용하면
간단하게 객체를 합쳐 새로운 객체로 반환할 수 있다.
let state = {
"items": [
{
"id": 1,
"name": "노른자 분리기",
"img": "../images/egg.png",
"price": 9900
},
{
"id": 2,
"name": "2020년 달력",
"img": "../images/2020.jpg",
"price": 12000
}],
"cartItems": [
{
"itemId": 1,
"quantity": 1
},
{
"itemId": 5,
"quantity": 7
}]
}
let newItem = {
"itemId": 2,
"quantity": 3
}
위와 같은 객체 데이터가 있다고 해보자.
cartItems라는 key에 newItem 객체를 추가하고 싶다면 어떻게 할까?
🧩 상태(state) 객체는 해당 변수에 바로 값을 할당할 수 없다는,
불변성(Immutability)을 가지고 있다는 사실을 염두에 두고
새로운 값을 추가한 새로운 객체를 만들어야 할 것이다.
const result = Object.assign({}, state, {
cartItems: [...state.cartItems, newItem]
})
/* newItem이 추가된 새로운 객체가 result에 담긴다 */
Object.assign()이라는 객체 메소드는 파라미터로 들어간 객체를 모두 합쳐준다.
첫 번째 파라미터 : 모든 객체가 합쳐서 모여지게 될 객체.
두 번째부터 마지막 파라미터 : 첫 번째 파라미터로 합쳐질 객체.
🧩 newItem을 다시 삭제하려면 어떻게 해야할까?
let removeItem = state.cartItems.filter(item => item.itemId !== newItem.itemId)
/* 삭제하고자 하는 newItem을 제외한 배열을 removeItem에 담는다 */
const result = Object.assign({}, state, {
cartItems: [...removeItem]
})
/* 원 배열 state에 newItem이 삭제된 배열인 removeItem을 합친다 */
🧩 newItem의 quantity 값을 수정하려면 어떻게 할까?
let idx = state.cartItems.findIndex(el => el.itemId === newItem.itemId)
/* newItem의 itemId값으로 인덱스를 먼저 찾아낸다 */
let setItem = [...state.cartItems]
/* 새로운 배열에 전체 배열을 복사해준다 */
setItem[idx].quantity = 1
/* 복사한 배열의 인덱스 값에 해당하는 배열의 수량에 수정값을 할당한다 */
let result = Object.assign({}, state, {
cartItems: [...setItem]
/* 기존 객체에 수정된 배열을 Object.assign()으로 합쳐준다 */
})
위 코드를 Redux의 reducer에 적용하기 위해서는, switch로 action.type을 받아와 각각의 case를 설정해주고 result값을 리턴하면 된다.
const itemReducer = (state = initialState, action) => {
switch (action.type) {
case ADD_TO_CART:
return Object.assign({}, state, {
cartItems: [...state.cartItems, action.payload]
})
case REMOVE_FROM_CART:
let removeItem = state.cartItems.filter(item => item.itemId !== action.payload.itemId)
return Object.assign({}, state, {
cartItems: [...removeItem]
})
case SET_QUANTITY:
let idx = state.cartItems.findIndex(el => el.itemId === action.payload.itemId)
let setItem = [...state.cartItems]
setItem[idx].quantity = action.payload.quantity
return Object.assign({}, state, {
cartItems: [...setItem]
})
default:
return state;
}
}