리액트

[리액트] react.memo()로 불필요한 재평가 방지하기

MC류짱 2022. 12. 30. 21:03

react.memo()로 불필요한 재평가 방지하기

  • 현재 리액트는 컴포넌트가 가지고 있는 state가 바뀌면 그것들이 그 컴포넌트 함수가 재평가된다.
  • 문제는 이 때 state나 props에 아무 관련이 없는 자식 컴포넌트들도 다시 재평가 된다는 것이다.
  • 예를 들어 아래와 같은 상황이 있으면

  • App 컴포넌트에서 버튼을 누르면 state가 변경되므로 app컴포넌트가 재평가 되어 콘솔에 App RUNNING이 찍히고
  • 그 바로 아래 자식인 DemoOutput에서도 콘솔이 찍히고, 그 자식인 MyParagraph에서도 콘솔이 찍힌다.
  • 즉, 자식의 자식까지 모두 다 재평가 된다는 것이다. 간단한 앱이면 상관이 없지만 규모가 큰 프로젝트면 이를 방지해야한다.
  • 이를 방지하기 위해 react.memo()를 사용한다.

 

react.memo()로 감싸주기

  • 이런 식으로 자식 컴포넌트에서 props의 데이터가 변하는 상황에서만 이 컴포넌트가 재평가 되게 해준다.
  • 이런 형태는 함수형 컴포넌트에서만 가능하다.
  • 이제는 콘솔에 App RUNNING만 찍힌다.
  • 하지만 이 역시 최적화의 비용을 요구한다. 예를 들어 React.memo()로 감싼 컴포넌트는 state가 바뀔 때
  • 이 컴포넌트의 기존의 props와 현재의 props를 따로 저장하여 비교 할 것이기 때문이다.
  • 이 최적화 비용이 크냐 아니면 재평가 비용이 크냐고 물어본다면 쉽게 답할 수는 없다.
  • (하지만 자식이 많을 수록 효율적이기는 하다)

 

예외

  • ※ 하지만 props에 배열이나 객체, 함수를 넘겨주면 같지 않다고 판단하여 재평가된다.
  • 자바스크립트에서 false === false -> true, 'hi' === 'hi' -> true 이지만,
  • [1, 2, 3] === [1, 2, 3]은 false이다.

 

해결법

  • 리액트에서 객체나 함수등을 생성하고 저장하는 방식만 조금 변경해주면 된다.
  • useCallback 훅을 사용하면 된다.
  • 이는 useCallback 훅을 사용해 저장한 함수를 리액트 내부 저장 공간에 저장해서,
  • 함수 객체가 실행될 때마다 재사용할 수 있게 해준다.

  • 위와 같이 useCallback으로 묶어 첫 번째 인자에 함수를 전해주면 된다.
  • 두 번째 인자로는 의존성의 배열을 준다.