컴포넌트가 렌더링된 후 사이즈를 측정하기 위해 useEffect()
를 이용해 setSize()
를 실행하는 코드가 있습니다.
해당 컴포넌트는 브라우저의 크기가 변동됨에 따라 크기가 변경될 수 있어 window.addEventListener('resize', )
를 이용해 다시 사이즈를 측정합니다.
size
setSize()
를 실행하는 함수에 매개변수로 size
를 넣는 것은 무한루프에 빠질 수 있어 올바르지 않다.useLayoutEffect()
: DOM이 변경된 직후 실행됩니다.
※ 레이아웃이나 스타일 계산이 완료되기 전일 수 있습니다.
requestAnimationFrame()
: 레이아웃과 스타일 계산이 완료된 후 브라우저가 화면을 repaint
하기 직전에 실행됩니다. 때문에 정확한 크기 측정이 가능해집니다.
따라서 컴포넌트의 크기를 측정할 때에는
useEffect()
대신 DOM이 변경되고 화면에 그려지기 전에 실행하겠다는 뜻을 가진 useLayoutEffect()
를 이용하고
레이아웃과 스타일 계산이 완료된 후에 실행되는 requestAnimationFrame()
를 사용하여 정확한 크기 계산을 합니다.
위 컴포넌트는 transition
속성이 있어 크기 변화에 딜레이가 있습니다.
그렇기 때문에 mainElement.addEventListener('transitionend', )
를 사용하였습니다.
만약 transition
속성이 없다면 ResizeObserver()
를 사용할 수 있습니다.
ResizeObserver()
를 사용하면 요소의 크기가 변경될 때 마다 콜백을 호출합니다.
트랜지션이 진행되는 동안 여러 번 크기 변화가 감지되어 불필요한 상태 업데이트가 발생할 수 있어
mainElement.addEventListener('transitionend', )
를 사용하였습니다.
requestAnimationFrame()
만 사용해도 repaint
직전에 실행되니까 굳이 useLayoutEffect()
를 사용하지 않아도 되지 않을까? 라는 의문이 생겨서 추가 검색을 해보았습니다.
DOM이 준비된 시점을 보장하기 위해 useLayoutEffect()
를 같이 사용해주는것이 좋다고 합니다.