개발일지

useLayoutEffect 본문

리액트 공식문서 스터디

useLayoutEffect

박수미/ 2024. 6. 11. 22:25

📌 useLayoutEffect란?

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

useLayoutEffect(setup, dependencies?)

📌 useLayoutEffect

브라우저가 화면을 다시 그리기 전에 useLayoutEffect를 호출하여 레이아웃을 측정합니다:

import { useState, useRef, useLayoutEffect } from 'react';

function Tooltip() {
  const ref = useRef(null);
  const [tooltipHeight, setTooltipHeight] = useState(0);

  useLayoutEffect(() => {
    const { height } = ref.current.getBoundingClientRect();
    setTooltipHeight(height);
  }, []);
  // ...

 

📍매개변수

  • setup: Effect의 로직이 포함된 함수입니다. 셋업 함수는 선택적으로 클린업 함수를 반환할 수 있습니다. 컴포넌트가 DOM에 추가되기 전에 React는 셋업 함수를 실행합니다. 변경된 의존성으로 다시 렌더링 할 때마다 React는 (클린업 함수를 정의한 경우) 먼저 이전 값으로 클리업 함수를 실행한 다음, 새 값으로 셋업 함수를 실행합니다. 컴포넌트가 DOM에서 제거되기 전에 React는 클린업 함수를 한번 더 실행합니다.
  • 선택적 dependencies: setup 코드 내에서 참조된 모든 반응형 값의 목록입니다. 반응형 값에는 props, state, 컴포넌트 본문 내부에서 직접 선언된 모든 변수와 함수가 포함됩니다. 린터가 React용으로 설정된 경우, 모든 반응형 값이 의존성으로 올바르게 지정되었는지 확인합니다. 의존성 목록은 일정한 수의 항목을 가져야 하며 [dep1, dep2, dep3]와 같이 인라인으로 작성해야 합니다. React는 Object.is 비교를 사용하여 각 의존성을 이전 값과 비교합니다. 이 인수를 생략하면 컴포넌트를 다시 렌더링 할 때마다 Effect가 다시 실행됩니다.

📍반환값

useLayoutEffct는 undefined를 반환합니다.

 

📍주의사항

  • useLayoutEffect는 훅이므로 컴포넌트의 최상위 레벨 또는 자체 훅에서만 호출할 수 있습니다. 반복문이나 조건문 내부에서는 호출할 수 없습니다. 필요하다면 컴포넌트를 추출하고 Effect를 그곳으로 이동하세요.
  • Strict Mode가 켜져 있으면 React는 첫 번째 실제 셋업 전에 개발 전용 셋업+클린업 사이클을 한번 더 실행합니다. 이는 클린업 로직이 셋업 로직을 "미러링"하고 설정이 수행 중인 모든 작업을 중지하거나 취소하는지 확인하는 스트레스 테스트입니다. 문제가 발생하면 클린업 함수를 구현하세요.
  • 의존성 중 일부가 컴포넌트 내부에 정의된 객체 또는 함수인 경우, Effect가 필요 이상으로 자주 다시 실행될 위험이 있습니다. 이 문제를 해결하려면 불필요한 객체 및 함수 의존성을 제거하세요. 또한 Effect 외부에서 state 업데이트와 비반응형 로직을 추출할 수도 있습니다.
  • useLayoutEffect 내부의 코드와 여기에서 예약된 모든 state 업데이트는 브라우저가 화면을 다시 그리는 것을 차단합니다. 과도하게 사용하면 앱이 느려집니다. 가급적이면 useEffect를 사용하세요.

📌 사용방법

1️⃣ 브라우저에서 화면을 다시 그리기 전 레이아웃 측정하기

대부분의 컴포넌트는 무엇을 렌더링할지 결정하기 위해 화면에서의 위치와 크기를 알 필요가 없습니다. 일부 JSX만 반환하기 때문입니다. 그런 다음 브라우저는 해당 컴포넌트의 레이아웃(위치 및 크기)을 계산하고 화면을 다시 그립니다.

때론 그것만으로는 충분하지 않을 수 있습니다. 마우스오버 시 요소 옆에 툴팁을 표시하는 것을 상상해 보세요. 공간이 충분하면 툴팁을 올바른 최종 위치에 렌더링 하려면 툴팁의 높이(즉, 상단에 표시하기에 충분한지 여부)를 알아야 합니다.

이렇게 하려면 두 번의 패스로 렌더링해야 합니다:

1. 툴팁을 원하는 위치에 렌더링합니다.(위치가 잘못된 경우에도)

2. 높이를 측정하고 툴팁을 배치할 위치를 결정합니다.

3. 올바른 위치에 툴팁을 다시 렌더링합니다.

이 모든 작업은 브라우저가 화면을 다시 그리기 전에 이루어저야 합니다. 사용자가 툴팁이 움직이는 것을 보지 않기를 원합니다. 브라우저가 화면을 다시 그리기 전에 useLayoutEffect를 호출하여 레이아웃 측정을 수행합니다:

function Tooltip() {
  const ref = useRef(null);
  const [tooltipHeight, setTooltipHeight] = useState(0); // You don't know real height yet
                                                         // 아직 실제 height 값을 모릅니다.

  useLayoutEffect(() => {
    const { height } = ref.current.getBoundingClientRect();
    setTooltipHeight(height); // Re-render now that you know the real height
                              // 실제 높이를 알았으니 이제 리렌더링 합니다.
  }, []);

  // ...use tooltipHeight in the rendering logic below...
  // ...아래에 작성될 렌더링 로직에 tooltipHeight를 사용합니다...
}

단계별 작동 방식은 다음과 같습니다:

1. Tooltip은 초기 tooltipHeight = 0으로 렌더링 됩니다.(툴팁의 위치가 잘못 지정될 수 있음).

2. React는 이를 DOM에 배치하고 useLayoutEffect에서 코드를 실행합니다.

3. useLayoutEffect는 툴팁 콘텐츠의 높이를 측정하고 즉시 다시 렌더링을 촉발합니다.

4. Tooltip이 실제 tooltipHeight로 다시 렌더링 됩니다.(툴팁이 올바르게 배치됩니다)

5. React가 DOM에서 이를 업데이트하면 브라우저에 툴팁이 최종적으로 표시됩니다.

'리액트 공식문서 스터디' 카테고리의 다른 글

useMemo  (0) 2024.06.17
useEffect, useLayoutEffect 발표 자료  (1) 2024.06.13
useEffect  (0) 2024.06.04
2회차 발표  (0) 2024.05.31
useRef  (0) 2024.05.30