목차
1. React.memo
2. useCallback
<리렌더링 발생 조건>
1. 컴포넌트에서 스테이트가 바뀌었을 때
2. 컴포넌트가 내려받은 props가 변경되었을때
3. 부모 컴포넌트가 리렌더링 된 경우 자식 컴포넌트는 모두!
화면 좌측에 있는 버튼을 한 번 눌렀을 뿐인데, 콘솔창을 보면 부모 컴포넌트인 App컴포넌트 뿐 아니라 하단 Box 컴포넌트까지 전부 호출이 되는 모습을 볼 수 있다.
굳이 그럴 모든 컴포넌트가 호출될 필요가 있을까?
이런 경우 React.memo
를 사용해보자!
데이터를 메모리에 저장하는 행위를 캐싱
이라고 한다.
지금 사용해볼 React.memo
는 컴포넌트를 통으로 메모리에 저장하는
캐싱 방식을 사용한다는 점 기억하기 !
Box1.jsx를 export
할 때, React.memo
로 감싸 주면 !
count
버튼을 눌렀을 때 Box1 컴포넌트는 리렌더링 되지 않는 걸 볼 수 있다.
같은 방식으로 나머지 박스 컴포넌트들도 export
시 React.memo
로 묶어주면,
버튼 눌렀을 때, 부모 컴포넌트인 App 컴포넌트만 리렌더링 되는 모습을 볼 수 있다 !
React.memo
는 컴포넌트 자체를 캐싱, memoization
한다고 했다.
그럼 useCallback
은?
바로 인자로 들어오는 함수 자체를 memoization
한다!
만약 Box1이 카운트를 초기화 하는 애라면?
초기화 함수인 initCount
만든 후, props
로 Box1
컴포넌트에 연결해주면 버튼 누르면 count
기본값인 0으로 변경된다.
뭔가 이상한 점이 생겼다.
React.memo
를 사용했을 때는 ''App 컴포넌트가 렌더링 되었습니다.'' 하나만 떴었는데, 지금은 Box1 ~~ 까지 같이 뜬다.
그 이유는 함수형 컴포넌트
를 사용했기 때문이다.
아까 봤던 코드를 다시 보자.
const initCount = () => {
setCount(0);
};
얘는 App
이라는 컴포넌트가 리렌더링 될 때 같이 리렌더링 된다.
function Box1({ initCount }) {
console.log('Box1 컴포넌트가 렌더링되었습니다!');
return (
<div style={style}>
<button
onClick={() => {
initCount();
}}
>
초기화
</button>
</div>
);
}
여기 온클릭 부분도 initCount
가 다시 만들어 졌기 때문에, props
로 새로운 값을 전달받았다고 여겨진다..
함수도 객체로 여겨지기 때문에, 별도의 공간에 별도의 주소값이 저장됨..
함수형 컴포넌트들이 리렌더링 되면서 값이 다시 만들어 질 때, initCount
얘는 새로운 주소값을 다시 받기 때문에 그렇다.
불변성 기억하기 !
별도의 공간에 initCount
를 저장해놓고, 특정 조건이 아니면 변경되지 않도록 장치를 해놓는게 좋겠음 -> useCallback
이용해서~
의존성 배열!
근데 이거 콘솔 한 번 찍어보자.
카운트 + 눌렀다가 초기화 버튼 누르면, 0에서 0으로 변경되었습니다.
이렇게 뜬다.
만약 카운트 5까지 눌러놓고 초기화하면, “5에서 0으로 변경되었습니다.” 이렇게 떠야하는거 아닌가? 싶지만…
useCallback
이 함수를 저장하는게, 카운트가 0인 시점이기 때문에 그렇게 뜨는 것!
다시 말하면 저장하는 시점에 이미 setCount(0)
이라고 내부에 저장되어 있기 때문이다.
카운트가 변경될 때 useCallback
내부 식이 다시 저장되게 하기 위해서 dependency array
를 사용한다.
count
가 변경되는 시점에만 useCallback
되도록 해줘~ 라는 의미로
마지막에 [count] 적어주면,
'2에서0으로 변경되었습니다.' 라고 이렇게 잘 뜨는 걸 볼 수 있다.