우리가 자주 사용하는 useEffect()
훅 말고도 react는 useLayoutEffect()
라는 훅을 제공한다. 이 훅은 useEffect()
와 동일하게 컴포넌트의 마운트 이후 실행된다는 점은 비슷하다. 차이점은 useEffect()
는 비동기적으로 실행되고, useLayoutEffect()
훅은 동기적으로 실행된다는 점이다.
useEffect()
는 화면이 다 그려진 이후 (= paint와 layout 과정이 이루어진 후) 비동기적으로 실행된다. useLayoutEffect()
는 렌더링 후 layout과 paint과정이 일어나기 전 동기적으로 실행된다.즉, useLayoutEffect()
훅은 다른 콜백 함수들의 실행이 종료되어야 실행된다는 뜻이고, 깜빡임 현상이 일어나지 않는 효과가 있다. 반면 useEffect()
는 종료 여부와 상관없이 콜백 함수들을 기다리지 않는다는 뜻이고, 때에 따라서 깜빡임 현상이 발생할 수 있다.
react 공식문서에서는 아래와 같은 useLayoutEffect()
훅의 특징 때문에 useEffect()
훅의 사용을 더욱 권장하고 있다.
실행되는 동안 브라우저는 컴포넌트의 렌더링을 중단한다. 따라서 useLayoutEffect() 내부에서 오랫동안 실행되는 작업을 수행하면 브라우저의 응답성이 떨어질 수 있다.
useEffect()
훅은 비동기적으로 실행되기에 브라우저의 응답성에 영향을 주지 않는다.
useLayoutEffect()
의 특징은 렌더링 작업이 끝난 직후 동기적으로 호출된다는 특징을 갖고 있다. 이 특징을 응용해야하는 로직이 필요할 때, 이 훅을 사용하면 좋다. 예를 들어, DOM 요소의 크기나 위치와 같은 값을 측정하거나 조작하는 작업이 필요할 때 사용하면 좋다.
import React, { useLayoutEffect, useRef } from 'react';
function Component() {
const ref = useRef<HTMLDivElement | null>(null);
useLayoutEffect(() => {
// DOM 요소의 크기를 측정하거나 조작하는 작업
const width = ref!.current!.offsetWidth;
const height = ref!.current!.offsetHeight;
// ... 작업 수행 ...
}, []);
return <div ref={ref}>Some content</div>;
}
혹은, 계산된 state 값을 화면에 표출해야 하는 경우에도 사용된다.
import React, { useState, useLayoutEffect } from 'react';
const MyComponent = () => {
const [value, setValue] = useState(0);
// 컴포넌트가 렌더링 이후에 실행되는 효과
useLayoutEffect(() => {
setCalculatedValue(newValue);
}, []); // 두 번째 매개변수로 빈 배열을 전달하여 최초 한 번만 실행되도록 합니다.
return <div>{calculatedValue}</div>;
}
하지만
useEffect()
의 깜빡임 현상은 0.25배속으로 봐도 확인이 힘들 정도로 미미하며, 성능상으로도useLayoutEffect()
보다 효율적이기에, 특별한 경우가 아니라면useEffect()
를 사용하는 것을 권장한다.