react에서 불변성을 유지하는 코드를 작성하기 쉽게 해주는 라이브러리
쉽게 말하면
상태를 변경하지 않는 것
이다.
상태를 변경하는데, 상태를 변경하지 않으면서 원하는 상태를 바꾼다는게 모순적인 거 같지만 ...
react는 기본적으로 부모 컴포넌트가 리렌더링을 하면 자식 컴포넌트도 리렌더링하게 된다. 즉, 얕은 비교를 통해 새로운 값인지 아닌지를 판단한 후 새로운 값인 경우 리렌더링을 하게 된다.
여기서 얕은 비교란 ! 객체 , 배열, 함수와 같은 참조 타입들을 실제 내부 값까지 비교하지 않고 동일 참조인지(동일한 메모리 값을 사용하는지)를 비교하는 것을 뜻합니다.
state.push(1)
을 통해 state 배열에 직접 접근하여 요소를 추가한다.setUsers(state.array.concat(user));
const onRemove = id => {
// user.id 가 id 인 것을 제거
setUsers(users.filter(user => user.id !== id));
};
const onToggle = id => {
setUsers(
users.map(user =>
user.id === id ? { ...user, active: !user.active } : user
)
);
};
setState(state => {...state, key: value})
setState(state => {..._.omit(state, 'deleteKey')})
setState(state => {...state, key: newValue})
immer.js
를 이용한 일반 객체 또는 배열 다루듯 사용하면 immer가 불변성을 지켜준다
!import produce from "immer";
const baseState = [
{
todo: "Learn typescript",
done: true
},
{
todo: "Try immer",
done: false
}
];
const nextState = produce(baseState, draftState => {
draftState.push({ todo: "Tweet about it" });
draftState[1].done = true;
});
immer에서 우리가 쓸 함수는 오직 produce
만 알면 된다. 2가지의 파람을 가져오고 첫번째는 수정하고 싶은 객체/배열 , 두번째는 첫번째 파라미터에 할당된 객체/배열을 바꾸는 함수이다.
const initialState = [{ name: "nkh", address: { city: "seoul" } }];
export default function auth(state = initialState, action) {
produce(state, draft => {
switch (action.type) {
case SET_INFO:
draft[0].name = action.data.name;
draft[0].address.city = action.data.city;
break;
case ADD_INFO:
draft.push({ name: "hhh", address: { city: "zzz" } });
default:
return draft;
}
});
}
const byId = (state, action) =>
produce(state, draft => {
switch (action.type) {
case RECEIVE_PRODUCTS:
action.products.forEach(product => {
draft[product.id] = product;
});
break;
}
});
const byId = (state, action) => {
switch (action.type) {
case RECEIVE_PRODUCTS:
return {
...state,
...action.products.reduce((obj, product) => {
obj[product.id] = product;
return obj;
}, {})
};
default:
return state;
}
};