// reducer.js
const initialState = {
contactList: [],
};
function reducer(state = initialState, action) {
const { type, payload } = action;
switch (type) {
case "DELETE_CONTACT":
state.contactList.forEach((item, i) => {
if (item.tel === payload.tel) {
state.contactList.splice(i, 1);
}
});
return {
...state,
// 문제를 일으키는 부분
contactList: state.contactList,
};
default:
return { ...state };
}
}
export default reducer;
contactList 배열은 name과 tel이라는 프로퍼티를 갖고 있는 객체를 담고 있는 배열이다.
내가 원하던 동작은 useDispatch로 type: "DELETE_CONTACT" 를 보냈을 때 contactList에 담겨있는 객체 중에 tel프로퍼티가 payload로 전달된 tel과 일치하다면 해당 객체를 contactList에서 제거하고자 하는게 목표였다.
콘솔로 찍어보면 state는 정상적으로 변경되지만 컴포넌트가 리렌더링 되지 않았다.
그 이유는 react-redux가 state가 변했는지 확인하는 검증 방식에 있었다.
react-redux는 state의 모든 자식 요소를 === 일치 연산자를 사용해서 비교하기 때문에 내가 .splice 메서드를 통해 contactList를 변경했을지언정 contactList의 참조는 이전과 동일하기 때문에 === 로 비교했을 때 true가 나온다.
따라서 해당 배열이 변경되지 않은것으로 판단되어 컴포넌트가 리렌더링 되지 않은 것이다.
따라서 해결책으로는 아래와 같이 Destructuring을 통해 깊은 복사를 하거나 아니면 .filter 메서드 등을 사용해서 새로운 배열이 리턴되게 하여 해결할 수 있다.
return {
...state,
// Destructuring 을 이용한 방법
contactList: [...state.contactList],
};
case "DELETE_CONTACT":
return {
...state,
contactList: deleteContact(state.contactList, payload),
};
. . .
function deleteContact(contactList, payload) {
return contactList.filter((contact) => {
return contact.tel !== payload.tel;
});
}
[Stack overflow] My Redux state has changed, why doesn't React trigger a re-render?