아무리 useReducer를 쓴다 해도 중첩된 객체가 많으면 많을수록 코드는 복잡해진다. 좀 더 직관적으로 간단하게 코드를 짜고 싶다면 Immer 라이브러리를 사용하면 된다!
Immer와 useImmer 설치하려면 터미널에
yarn add immer use-immer
입력!!
Immer를 사용하면 가변성 객체를 다루는 것처럼 손쉽게 update와 수정,변경이 가능하다!
일반 객체를 update하는 것처럼 사용하지만 Immer 내부에서 새로운 객체를 만들어서 필요한 것만 업데이트 해서 새로운 객체를 만들어내는 원리이다!
useState 대신 useImmer를 호출하기 위해
const [person, updatePerson] = useImmer(initialPerson);
작성한다! 대신 두 번째 원소에 setPerson 대신 updatePerson 이라고 적는데 통상적으로 Immer를 사용할 땐 set 대신 update를 사용하는 것 같다!
function updateName(name) {
updatePerson(draft => {
draft.name = name;
});
}
이런식으로 사용하면 되는데 스프레드 연산자를 쓸 필요도 없고 정말 간단하게 코드를 짤 수 있다!!
내가 작성한 코드
updatePerson((person) => person.mentors.push({ name, title }));
에러
원인
괄호가없는 화살표 함수는 return
문으로 작동하기 때문이다.
immer의 produce
함수는 아무것도 return
하지 않는 void
타입의 함수인데 괄호가 없는 화살표 함수는 return
을 적어주지 않아도 return
기능을 실행하기 때문에 에러가 난 것이다.
그래서 아래처럼 코드를 수정해주었다.
수정한 코드
updatePerson((person) => {
person.mentors.push({ name, title });
});
보다 보니 또 한 가지 이슈를 발견했다.
멘토 삭제 시 멘토 이름 중 존재하지 않는 이름을 입력했을 때 마지막 배열 원소가 삭제되는 것이다!
내가 작성한 코드
updatePerson((person) => {
const index = person.mentors.findIndex((m) => m.name === deleteMentor);
person.mentors.splice(index, 1);
});
여기에 아래 조건문을 하나 추가해주면 정상 작동이 된다.
if (index < 0) return;
수정한 코드
updatePerson((person) => {
const index = person.mentors.findIndex((m) => m.name === deleteMentor);
if (index < 0) return;
person.mentors.splice(index, 1);
});
실제 Immer 공식 문서에서도 안내하고 있는 예시이다.
https://immerjs.github.io/immer/update-patterns/#array-mutations