1. 스팩 정의

기능 스팩

  1. 컴포넌트의 width, height를 측정하고, 이를 리턴한다.
  2. 컴포넌트의 너비/높이가 바뀌면, 바뀐 너비/높이를 새롭게 구한다.

개발 스팩

  1. ref를 넘겨주면, width와 height값을 리턴하는 훅으로 만들면 좋을 듯하다.

    <aside> 💡 함수가 아닌 훅을 이용하는 이유

    커스텀 훅 안에어서는 리액트 훅을 사용할 수 있다. 리액트 훅 중 useEffect는 컴포넌트가 렌더링된 후 실행되는 훅이다. 컴포넌트의 사이즈를 측정하기 위해서는 컴포넌트가 마운트된 후 실행되어야 하기 때문에 커스텀 훅으로 만들어줄 것이다.

    </aside>

2. 개발

export default function useComponentSize(ref:React.RefObject<any>) {
	const [componentSize,setComponentSize] = useState({
		width : 0,
		height : 0
	})
	
	const handleResize = React.useCallback(()=>{ // 컴포넌트가 렌더링될 때마다 재선언을 할 수 있으니, useCallback으로 메모이제이션을 한다.
		if(!ref.current){ // 아직 ref가 돔에 박히지 않았을 때이다. (ref가 박힐 돔이 렌더링되면, ref.current는 해당 돔을 가리키게 된다.
			return;
		}
		const height = ref.current.offsetHeight; 
		const width = ref.current.offsetWidth;
		setComponentSize({
			width,height
		})
	},[ref])
	
	React.useLayoutEffect(()=>{
		if(ref.current){
			ref.current.addEventListener('load',handleResize);
		}else{
			handleResize();
		}
		window.addEventListener('resize',handleResize); 
		return(()=>{
			window.removeEventListener('resize',handleResize);
		})
	},[ref,handleResize])
	
	return componentSize
}

<aside> 💡 offsetHeight, offsetWidth

: padding + border를 포함한 높이/너비

</aside>

<aside> 💡 React.useCallback

: 리렌더링 간에 함수 정의를 캐싱해준다. 즉, 메모이제이션을 한다.

</aside>

<aside> 💡 React.useLayoutEffect

useEffect는 브라우저가 화면을 그린 후에(layout, paint 후) 비동기적으로 실행되는 데 반해 useLayoutEffect는 브라우저가 DOM을 변경한 후, 화면에 변경 사항을 그리기 전(layout, paint 전)에 동기적으로 실행이 된다. 화면에 변경 사항을 그리기 이전에 실행하기에 컴포넌트 본연의 사이즈를 구하기 위해서는 useEffect보다 useLayoutEffect가 더 적합하다.

useLayoutEffect를 사용할 경우, 화면에 그리기 전 동기적으로 실행하기 때문에 사용자는 깜빡임을 보지 않는다.

</aside>

결과

Untitled

훅 안에서 width와 hegiht를 console을 찍어보았다(:17). 처음에 0 0은, 훅 자체는 컴포넌트가 마운트 되기 전에 실행되기 때문이다. 그리고 컴포넌트가 마운트 되면 handleResize가 실행되며 setComponentSize라는 setState함수가 실행이 된다. 이 떄 훅이 한 번 더 호출되는 것이다.