
immer 라이브러리를 사용하면, 구조가 복잡한 객체도 매우 쉽고 짧은 코드를 사용하여 불변성을 유지하면서
업데이트를 할 수 있습니다.
첫번째 파라미터는 수정하고 싶은 무엇이고, 두번째 파라미터는 그 무엇을 어떻게 업데이트 할지 정의하는 함수입니다.
대부분의 경우 ... 연산자 또는 배열 내장함수를 사용하는건 그렇게 어렵지는 않지만 데이터의 구조가 조금 까다로워지면 불변성을 지켜가면서 새로운 데이터를 생성해내는 코드가 조금 복잡해집니다.
const state = {
posts: [
{
id: 1,
title: '제목입니다.',
body: '내용입니다.',
comments: [
{
id: 1,
text: '와 정말 잘 읽었습니다.'
}
]
},
{
id: 2,
title: '제목입니다.',
body: '내용입니다.',
comments: [
{
id: 2,
text: '또 다른 댓글 어쩌고 저쩌고'
}
]
}
],
selectedId: 1
};
여기서 posts 배열 안의 id 가 1 인 post 객체를 찾아서, comments 에 새로운 댓글 객체를 추가해줘야 한다고 가정하고 immer 을 쓰지 않고 바꾸어 봅시다.
const nextState = {
...state,
posts: state.posts.map(post =>
post.id === 1
? {
...post,
comments: post.comments.concat({
id: 3,
text: '새로운 댓글'
})
}
: post
)
};
이렇게 구조가 좀 복잡해지고 코드 가독성도 떨어집니다. 아래는 immer 을 사용한 경우 입니다.
//npm install immer
//import produce from 'immer'
기본값 : produce(state, draft => {})
const nextState = produce(state, draft => {
const post = draft.posts.find(post => post.id === 1);
post.comments.push({
id: 3,
text: '새로운 댓글'
});
});
새로운 예시
import produce from 'immer';
const state = {
todos: [
{ id: 1, text: 'Buy milk', completed: false },
{ id: 2, text: 'Do laundry', completed: false },
{ id: 3, text: 'Clean room', completed: false },
]
};
const newState = produce(state, draftState => {
draftState.todos[1].completed = true;
draftState.todos.push({ id: 4, text: 'Walk the dog', completed: false });
});
console.log('Original state:', state);
console.log('New state:', newState);