Counter 예제와 이전 포스팅인 Redux #8에서 Todos를 만들어보면서 한 페이지에 같이 컴포넌트를 두어봤는데 Todos에서 상태가 변할 때 Counter쪽에 있는 컴포넌트에서도 리렌더링되는 것을 확인했다. 이유는CounterContainer.jsx에서 useSelector를 통해서 상태를 가져올 때 useSelector를 통해 매번 새로운 객체를 만들고 반환해주었기 때문이다.
CounterContainer.jsx
export default function CounterContainer() {
const { number, diff } = useSelector(state => ({
number: state.counter.number,
diff: state.counter.diff,
}));
...
개별적으로 새로운 객체를 만들어서 반환하지 않고 바로 state를 반환하는 방법.
CounterContainer.jsxexport default function CounterContainer() { const number = useSelector(state => state.counter.number); const diff = useSelector(state => state.counter.diff);
...
## 최적화 방법2
> 이 두번째 방법도 귀찮기 때문에 방법3을 쓸 것이다.
두번째 인자에 아래와 같이 equal함수를 넣어줘야 한다. 최적화 방법1처럼 하나씩 빼낼 때는 equal함수에 단일적으로 하나씩 비교해줘서 자동으로 최적화 됬던 것이고 객체일 때는 두 개를 다 비교해줘야 한다.
CounterContainer.jsx
```jsx
export default function CounterContainer() {
const { number, diff } = useSelector(
state => ({
number: state.counter.number,
diff: state.counter.diff,
}),
(left, right) => {
return left.number === right.number && left.diff === right.diff;
}
);
...
👏 shallowEqual을 react-redux에서 빼내서 사용하면 끝!
CounterContainer.jsx
export default function CounterContainer() {
const { number, diff } = useSelector(
state => ({
number: state.counter.number, // number에는 state -> counter 안에 있는 number를 넣어주겠다.
diff: state.counter.diff,
}),
shallowEqual
);
만약 depth가 2이상인 객체는 정상적으로 비교하지 못한다! 👏 그런데 불변성을 유지하면서 리덕스를 다룬다면 문제없다.
만약 아래와 같이 있다고 가정하면 shallowCopy는
(left, right) => left.a === right.a && left.b === right.b
이렇게 depth1까지만 비교하기 때문에 만약에 a 객체 내에서 z값이 6으로 바뀌었다고 하면 감지해내지 못한다.
그래서 리덕스에서 불변성을 유지하면서 a.z값을 바꾸면 결국 a자체도 바뀌는거니까 감지해낼 수 있다.
const object = {
a: {
x: 1,
y: 2,
z: 3,
},
b: 1
만약 무거운 렌더링이 자주일어나는 상황이라면 해주면 좋겠지만 안해도 충분히 빠르다. 모든걸 최적화해야 하는데 하면서 스트레스 받지 않아도 된다.
👏 즉, 최적화는 렌더링되는 내용이 많거나 렌더링이 엄청 자주 일어나면 고민하자.
1, 2 성능 동일하다. 아무거나 쓰면 된다. 단, 방법2를 사용했을 때는 꼭 equal함수를 넣어줘야 한다. react-redux에서 빼서 shallEqual 넣자.