이전 회사에서 쇼핑몰 프로젝트를 진행하다 페이지 렌더링될때 브라우저가 보여주기 전에 데이터 페칭을 하기 위해, useEffect 이 아닌 useLayoutEffect 를 사용한 경험이 있다.
과연 이게 맞는 방법인가를 생각하다. useEffect와 useLayoutEffect 의 차이점을 알면 그 사용법을 정확하게 알 수 있을 것 같다.
우선 useEffect 와 useLayoutEffect 의 코드를 보겠습니다.
useEffect
useEffect(()=> {
effect
return () => {
cleanup
}
},[input])
useLayoutEffect
useLayoutEffect(()=> {
effect
return(()=> {
cleanup
})
},[input])
리액트 공식 독에도 useEffect 와 useLayoutEffect 가 형태가 같다고 설명을 한다.
하지만 둘의 차임점은 이벤트 호출시기에 차이점을 둔다.
useEffect 는 브라우저에 화면이 그려지고 난 후에 실행이 되고, useLayoutEffect 는 브라우저에 화면이 그려지기전에 실행이 된다는 점이다. 모든 DOM 변경 후에 동기적으로 발생한다.
useLayoutEffect 의 설명 팁에 useEffect 를 사용하고 문제있으면, useLayoutEffect 를 사용하라고 권장한다.
서버 렌더링 하는 경우 자바스크립트가 모두 다운로드 될 때까지 useEffect 와 useEffectLayout 둘중 어느것도 실행이 되지 않는다.
그래서 서버에서 렌더링되는 컴포넌트에 useLayoutEffect를 사용하는 것을 React가 경고하는 이유이다.
이를 수정하기 위해선 최초 렌더링시에는 필요하지 않다면, useEffect 의 effect 안에 실행하거나, 클라이언트렌더링이 완료될때까지 컴포넌트 노출을 지연하는 방법을 사용하도록하라는 이야기이다.
서버렌더링이 완료되지 않은 상태에서 레이아웃 컴포넌트를 노출을 지연하는 방법은 이렇게 하라고 한다.
이런 방법으로 자바스크립트 코드가 주입되기전에 깨져 보일 수 있는 UI 는 표현되지 않게 된다.
import ChildComponent from './ChildComponent';
const [showChild, setShowChild] = useState(false);
useEffect(()=>{
setShowChild(true);
},[]);
return (
<>
{showChild && <ChildComponent />}
<>
)
그리고 유명하다는 깃허브 Hook flow 의 사진을 첨부했다.
LayoutEffect 가 실행되고 Browser paints scrren 후에 Effect 가 실행이 되어진다고 되어있다.
결론
1. 우선적으로 useEffect 를 사용해라!
2. useLayoutEffect를 사용은 제한적으로 사용해라
3. LayoutEffect -> 브라우저 그리기 -> useEffect 순으로 간다.