😥 두나무의 요청으로 클론 사이트 배포를 중단하였습니다...
💁♂️ 레포 링크
반응형을 개발할 때 보통 media tag에 조건을 달아 display: none을 적용하는 방식으로 필요없는 요소를 감춘다.
갱신이 잦은 요소가 아니라면 그것으로 충분하겠지만 리랜더링이 빈번하게 일어나는 요소라면 어떨까?
당연히 DOM에 존재하지 않게 하는 것이 성능 개선에 도움이 될 것이다.
따라서 조건에 따라 아예 컴포넌트를 페이지에 랜더링하지 않는 방법을 선택했다
미디어 태그에서 자동으로 viewport의 width값을 측정하는 것과 달리
컴포넌트에서 width 값을 사용하기 위해선 직접 값을 측정해야 한다.
import React, { useCallback, useEffect, useState } from "react";
const withSize = () => (OriginalComponent) => (props) => {
const [widthSize, setWidthSize] = useState(window.innerWidth);
const [heightSize, setHeightSize] = useState(window.innerHeight);
const handleSize = useCallback(() => {
setWidthSize(window.innerWidth);
setHeightSize(window.innerHeight);
}, []);
useEffect(() => {
window.addEventListener("resize", handleSize);
return () => {
window.removeEventListener("resize", handleSize);
};
}, [handleSize]);
return (
<OriginalComponent
{...props}
widthSize={widthSize}
heightSize={heightSize}
/>
);
};
export default withSize;
HOC 패턴을 사용하여 간단하게 만들어 보았다.
다만 이 코드에는 문제가 있는데 resize 이벤트가 발생할 때 너무 많은 이벤트가 한번에 발생한다는 것이다.
많은 연속적인 이벤트 발생 중 하나만 캐치하는 방법이 있지만 여기선 throttle을 사용해 보겠다.
lodash를 사용하면 쉽게 throttle을 구현할 수 있다.
import React, { useCallback, useEffect, useState } from "react";
import { throttle } from "lodash";
const withSize = () => (OriginalComponent) => (props) => {
const [widthSize, setWidthSize] = useState(window.innerWidth);
const [heightSize, setHeightSize] = useState(window.innerHeight);
const handleSize = useCallback(() => {
setWidthSize(window.innerWidth);
setHeightSize(window.innerHeight);
}, []);
useEffect(() => {
window.addEventListener("resize", throttle(handleSize, 200));
return () => {
window.removeEventListener("resize", handleSize);
};
}, [handleSize]);
return (
<OriginalComponent
{...props}
widthSize={widthSize}
heightSize={heightSize}
/>
);
};
export default withSize;
다음과 같이 window.addEventListener로 이벤트에 handleSize 함수를 등록할 때 throttle을 사용하므로써 이벤트 발생을 200ms마다 한번씩만 처리할 수 있다.
Thanks a lot for sharing!JOKER123