몽환화

[React] useLayoutEffect, useDebugValue 본문

Front/React

[React] useLayoutEffect, useDebugValue

hyeii 2024. 5. 6. 14:19

useLayoutEffect

 

브라우저가 화면을 다시 채우기 전에 실행되는 버전의 useEffect

하하하하하하

 

그래도 알아보긴 하자 

 

기본적인 사용 방식은 useEffect와 같다

컴포넌트의 최상위 레벨에서 또는 자체 훅에서만 호출할 수 있다.

 

예시)

대부분의 컴포넌트는 무엇을 렌더링할지 결정하기 위해 화면에서의 위치와 크기를 알 필요까지는 없다!  그러나 가끔 예외의 경우가 존재하는데, 마우스오버 시 요소 옆에 툴팁을 표시하는 경우 등이 있다. 공간이 충분하다면 툴팁이 적당히 표시되면 되지만, 공간이 충분하지 않다면 툴팁을 아래에 표시하는 등 위치를 변경할 필요성이 있다. 이를 위해서 툴팁의 렌더링을 위해 화면에서의 위치를 알아야 한다.

 

순서는 다음과 같다 

  1. 툴팁을 원하는 위치에 렌더링한다(위치가 잘못된 경우에도).
  2. 높이를 측정하고 툴팁을 배치할 위치를 결정한다.
  3. 올바른 위치에 툴팁을 다시 렌더링한다.

이 모든 작업은 브라우저가 화면을 다시 그리기 전에 이루어져야 한다! 그래서 useLayoutEffect를 호출한다

 

  1. Tooltip은 초기 tooltipHeight = 0으로 렌더링된다(따라서 툴팁의 위치가 잘못 지정될 수 있음).
  2. React는 이를 DOM에 배치하고 useLayoutEffect에서 코드를 실행한다.
  3. useLayoutEffect는 툴팁 콘텐츠의 높이를 측정하고 즉시 다시 렌더링을 촉발한다.
  4. Tooltip이 실제 tooltipHeight로 다시 렌더링된다(따라서 툴팁이 올바르게 배치된다).
  5. React가 DOM에서 이를 업데이트하면 브라우저에 툴팁이 최종적으로 표시다.

 

 

결국 얘의 목적은 컴포넌트가 렌더링할 때 레이아웃의 정보를 사용하기 위한 것이다

 

useLayoutEffect는 브라우저가 다시 페인팅하는 것을 차단한다.

- React는 브라우저가 화면을 다시 그리기 전에 useLayoutEffect 내부의 코드와 그 안에서 예약된 모든 state 업데이트가 처리되도록 보장한다. 이를 통해 사용자가 첫 번째 리렌더링을 눈치채지 못하게 한 상태에서 툴팁을 렌더링하고, 측정한 후, 다시 툴팁을 렌더링하게 해준다. 즉, useLayoutEffect는 브라우저의 페인팅을 차단한다.

 

 

useEffect와 useLayoutEffect

 

useEffect

 

컴포넌트 렌더링 => 페인트 => useEffect 실행(비동기)

useEffect 내부에 dom에 영향을 주는 코드가 있다면 사용자는 화면의 깜박임을 볼 수 있다

 

useLayoutEffect

컴포넌트 렌더링 => useLayoutEffect 실행 => 페인트 (동기)

앞에꺼 끝나야 다음것이 실행되므로 dom에 영향을 주는 코드가 존재하더라도 깜박임은 없다 

 

 

결국 useLayoutEffect는 내부의 코드가 모두 실행된 후 paint작업을 하니까 사용자 입장에서는 오래 걸릴 수 있으니 사용을 지양하는 편이 좋단다

 

 

 


 

 

 

useDebugValue

프로덕션 웹서비스에서 사용하는 훅은 아니다

개발하는 과정에서 사용하는 거다

 

React DevTools에서 커스텀 훅에 라벨을 추가할 수 있게 해주는 것 => 사용자 정의 훅 내부의 내용에 대한 정보를 남길 수 있는 훅

오직 다른 훅 내부에서만 실행할 수 있으니 주의한다

컴포넌트의 top level에서 사용하면 아무것도 아니다

import { useDebugValue } from 'react';

function useOnlineStatus() {
  // ...
  useDebugValue(isOnline ? 'Online' : 'Offline');
  // ...
}

이런 식으로 훅 내부에서 useDebugValue를 호출하고 라벨을 달면

react 공식문서 예시

위와 같이 출력되어 해당 훅을 사용하고 있는지에 대한 여부를 확인할 수 있다.

 

useDebugValue(date, date => date.toDateString());

두번째 인수로 포맷팅 함수를 전달하면 이에 대한 값이 변경되었을 때만 호출되어 변경된 값을 노출시킬 수 있다. (첫 번째 인수의 값이 같으면 포매팅 함수는 호출되지 않는다)

 

 

 

 

 

참고자료

도서 :: 모던 리액트 Deep Dive 

https://ko.react.dev/reference/react/useDebugValue

https://react-ko.dev/reference/react/useLayoutEffect

https://pubudu2013101.medium.com/what-is-the-real-difference-between-react-useeffect-and-uselayouteffect-51723096dc19

https://medium.com/@jnso5072/react-useeffect-%EC%99%80-uselayouteffect-%EC%9D%98-%EC%B0%A8%EC%9D%B4%EB%8A%94-%EB%AC%B4%EC%97%87%EC%9D%BC%EA%B9%8C-e1a13adf1cd5