이전 구현 사항
애니메이션 효과를 구현하기 위해 브라우저 가로 크기를 가지고 있는 screenWidth 상태와 form 영역의 높이를 가지고 있는 height 상태를 이용해 inline-style로 변화를 주었습니다.
BottomSheet 컴포넌트는 screenWidth 내부 상태를 이용하기 때문에, resize 이벤트 발생 시 리렌더링 되고 있습니다.
useRef 이용하여 개선하기
useRef는 .current 프로퍼티에 변경 가능한 값을 담을 수 있고, 이 프로퍼티가 변경되더라도 리렌더링을 발생시키지 않습니다.
그래서 screenWidth 값을 useState가 아닌 useRef를 이용했습니다.
const screenWidthRef = useRef(window.innerWidth);
useRef는 DOM에 접근할 수 있습니다.
기존의 inline style은 screenWidth라는 내부 상태가 변했기 때문에 리렌더링 되면서 애니메이션이 적용되었는데, useRef는 리렌더링이 발생하지 않으므로 aside에 접근하여 style을 변경하도록 합니다.
const asideRef = useRef();
return (
<aside className={styles.sheet} ref={asideRef}>
...
</aisde>
)
resizeThrottle 함수는 resize 이벤트에 대하여 throttle 적용, 브라우저 크기 저장, aside DOM의 스타일을 변경하고 있습니다.
useEffect는 height 상태가 변하면 애니메이션 로직을 실행하며, 컴포넌트가 unmount 되면 resize 이벤트를 제거하고 있습니다.
const resizeThrottle = throttle(() => {
screenWidthRef.current = window.innerWidth;
translate3d(asideRef, screenWidthRef.current, height);
}, 700);
useEffect(() => {
window.addEventListener('resize', resizeThrottle);
translate3d(asideRef, screenWidthRef.current, height);
asideRef.current.style.bottom = `-${height}px`;
return () => window.removeEventListener('resize', resizeThrottle);
}, [height]);
코드 및 결과
resize 이벤트가 발생해도 더 이상 BottomSheet 컴포넌트가 리렌더링 되지 않고있습니다.