react immer library

johnque·2020년 2월 4일
0

React

목록 보기
7/17

Component를 리렌더링하고 최적화 할때, 불변성이 유지되어야 함

const obj = {
  a: 'hello',
  b: 12345
};

다음과 같은 객체에서

object.b = 678910;

이런식으로 바꾸게 되면 불변성이 깨짐

따라서 만약에 678910b에 들어가는 객체를 만들고 싶으면, 새로운 객체를 만들어서 값을 새롭게 넣어줘야 함

const obj = {
  a: 'hello',
  b: 12345
};

const nextObject = {
  ...object,
  b: 678910
};

이렇게 해야 obj의 값이 변경되지 않아서 좋음

배열같은 경우도 값을 삽입하는 push, 값을 빼는 splice를 사용할 것이 아니라 filter나 map, concat 등으로 새롭게 배열을 만들어내는 것으로 불변성을 지킴

단, 이를 코드로 구현하는게 생각보다 까다롭고 복잡한 것이 문제
아니, 그렇게 어렵지 않다고 하더라도 코드의 가독성이 많이 떨어짐

이럴때 사용하는 것이 바로 immer
immer라이브러리는 불변성을 해치는 코드도 대신 불변성을 유지해주는 든든한 역할을 수행함

yarn add immer

다음 명령어를 터미널에 입력하여, immer라이브러리를 설치함
파일에선 import할 때, import immer가 아닌 produce를 사용함
이유는 확실치 않지만, 불변성을 지키기위해 자체적으로 새롭게 객체를 만들어내는 점 때문에 produce라는 이름을 지은게 아닌가 생각함

import produce from 'immer';

위와 같이 선언

const a = {
	number: 1,
    numberr: 2,
};
const b = produce(a, draft => {draft.number += 1});
console.log(a);
console.log(b);
// 결과 a = {number:1, numberr:2}, b = {number:2, numberr:2}

immerproduce를 사용하면 a에서 조금 바뀐 b를 새로 만들어냄
이로써 불변성을 지켰다고 볼 수 있음

produce(a, draft)에서 a는 새롭게 만들어질 b에 복사할 대상이고, draft는 실제로 복사된 값임
즉, draft는 처음엔 a와 값이 완벽히 동일한데, 그대로 아무것도 건드리지 않으면, ba와 똑같은 값을 가지게 됨
하지만, draft => {draft.number += 1}처럼 안의 내용을 바꿔주게 되면 ba와 비슷하지만 내부가 바뀜 물론 그 전의 a, b가 값만 같을 뿐이지 같은 객체라곤 볼 수 없지만, 그래도 값이 같았는데 draft에 의해 아예 값이 다른 새로운 b를 만들 수 있음

immer를 쓸 경우는 concat 대신 push, map대신 find를 써서 해당 객체를 찾아내서 값을 변경하고, filter대신 findIndex를 로 찾아내서 해당 객체로부터 splice를 통해 제외시킴


immer의 경우, 꼭 불변성을 위해 반드시 사용해야 하는 것은 아님
immer를 굳이 사용할 때보다 기존의 코드가 불변성도 지키면서 간단할 경우, 사용하지 않아도 됨

예를 들어,

users: state.users.concat(user);

라는 코드가 있다고 치면, 이를 immer로 구현할 경우

users: produce(state, draft => {
  draft.users.push(user)
});

이런식이 됨. 이는 굳이 1줄로도 불변성을 지킬 수 있는 것을 굳이 3줄로 늘여써서 오히려 더 이해가 힘듦


추가사항

immer를 업데이트로 활용할 수 있는 방법

const updater = produce(draft => ~~~);

원래는 draft에 복사할 값인 state를 넣어줘야 하는데, 그냥 이렇게 draft만 넣는 경우가 있음

예를 들어,

const a = {
  b: 'hi',
  c: true
};

가 있을 경우, 이를 업데이트 해주는 방법이 존재

const updater = produce(draft => {draft.c = !draft.c});
const next = updater(a);

이런식으로 해주게 되면 next
{b:'hi', c:false}가 됨 이를 useState에 활용하면 좋음

useState에서는 함수형으로 useCallback안에서 값을 바꿔주게 되면 굳이 두번째 매개변수에 []안에 사용된 객체를 넣어주지 않아도 되었음 그 때 set~~~() 모양의 값을 정하거나 값을 바꾸는 함수를 넣을 수 있는데 여기에 immerproduceupdater를 사용하면 좀 더 쉽게 불변성 유지가능

profile
코딩의 고수가 되고 싶은 종한이

0개의 댓글