- 컴포넌트에서 state가 변경되었을 때
- 컴포넌트가 내려받은 props가 변경되었을 때
- 부모 컴포넌트가 리렌더링 된 경우 자식 컴포넌트 역시 전부 리렌더링
리액트에서 리렌더링 발생 횟수는 줄이는게 좋음(비용이 발생: Cost) 따라서 불필요한 렌더링을 막기위해 최적화 하는 방법은
1. memo(React.memo) : 컴포넌트를 캐싱
2. useCallback : 함수를 캐싱
3. useMemo : 값을 캐싱
리렌더링 발생 조건 3번의 내용과 같이 부모 컴포넌트가 리렌더링 되면 자식 컴포넌트도 같이 리렌더링 된다.그래서 이러한 부분을 React.Memo를 통해 해결 가능
- React.Memo는 컴포넌트를 메모리에 저장
메모리에 저장하고 필요할 때 가져다 사용하는 방식
이러면 부모 컴포넌트의 state변경으로 인해 props가 변경이 되지 않는 한 컴포넌트는 리렌더링 X
이를 컴포넌트 메모이제이션(memoization)이라고 부름
React.Memo를 사용하지 않았을 때
카운트 버튼(+,-)클릭시 box컴포넌트들도 리렌더링
React.Memo를 사용했을 때
카운트 버튼을 아무리 눌러도 box컴포넌트 들은 리렌더링이 되지 않는다.
- 사용법
export default React.memo(컴포넌트)
React.memo가 컴포넌트를 메모이제이션 했다면 useCallback은 인자로 들어오는 함수 자체를 메모이제이션한다.
initCount함수는 App컴포넌트에 있기때문에 App컴포넌트가 리렌더링 될때 같이 리렌더링 됨 그러면 Box1컴포넌트에 있는 initCount호출부분에서 props로 새로운 값을 받았다고 인식하기 때문에 다시 리렌더링 된다.
왜?
해당 예제에서 React.memo를 부여했음에도 카운트 버튼 클릭시 Box1이 리렌더링 되는 이유는 함수형 컴포넌트도 결국 함수이고 js에서 함수는 객체이기 때문에 Box1은 값이 변경될때 새로운 주소값을 받았다고 인식함 따라서 useCallback을 통해 불변성을 유지해줘야할 필요가 있음
함수 선언부에 내용을 useCallback으로 감싸주고
뒤에 의존성 배열을 넣어준다.
- 의존성 배열 사용법
useCallback을 사용할때 의존성 배열이 빈배열이면 의존성 배열은 첫 렌더링할때 내용을 스냅샷 찍어 놓기 때문에 카운트를 아무리 누른뒤 초기화를 눌러도 0에서 0으로 변경됐다고 나옴 따라서
이런 식으로 값을 지속적으로 바꿔줘야하는 스테이트를 넣으면 잘 작동한다.
Memo = memoization(기억하다)
useMemo는 value에 대한 memoization
즉 함수의 값에 대한 memoization
useCallback은 함수를 기억
useMemo는 함수의 '값'을 기억
- 사용 예제
해당코드는 for문을 통해서 굉장히 많은 수를 돌아서 출력하기 때문에 굉장히 무겁고 로딩이 느림 그래서
useMemo를 통해 heavyWork의 return값을 메모리에 저장하여 사용함으로서 리렌더링을 해도 값을 그대로 저장하고 있기 때문에 속도가 단축됨.
- 주의사항
useMemo를 남발하게 되면 메모리 확보를 너무 많이 하기 때문에 오히려 성능이 악화될 수 있음