이번 주담대 로직 중 마주친 이슈는 다음과 같습니다.
<aside>
☝🏻 리스트 형태의 컴포넌트의 height
가 정해진 영역을 넘어갈 시 overflow-y: auto
처리와 함께 리스트 하단 부분은 Blur 처리가 되어야 합니다.
</aside>
<aside> ✌🏻 스크롤 이벤트가 일어나 리스트 컴포넌트의 최하단 부분이 보이게 되면 Blur는 사라져야 합니다.
</aside>
ScrollWithBlur
컴포넌트에 들어오는 리스트 컴포넌트의 height
는 들어오는 데이터의 양에 따라 가변적인 크기를 가진다는 특징이 있어요.
부모 요소의 height
보다 자식 요소의 height
의 크기가 더 큰 것을 어떻게 판단할 수 있을까요? 🤔
해당 문제는 useRef
를 통해 요소에 접근하여 wrapperHeight
와 childrenHeight
를 가져와 둘의 크기를 비교하는 방식으로 접근했어요.
export const useWithBlur = () => {
const rootRef = useRef<HTMLDivElement>(null);
const childrenRef = useRef<HTMLDivElement>(null);
/** children이 root 요소의 height 넘는지에 대한 상태값 */
const [isOverflow, setIsOverflow] = React.useState(false);
useEffect(() => {
const wrapperHeight = rootRef.current?.clientHeight;
/** props로 전달받은 children의 height를 측정합니다. */
const childrenHeight = childrenRef.current?.getBoundingClientRect().height;
if (!wrapperHeight || !childrenHeight) return;
setIsOverflow(wrapperHeight < childrenHeight);
}, []);
return { rootRef, targetRef, isOverflow }
}
useWithBlur
훅을 사용하는 ScrollWithBlur
의 컴포넌트 구조는 다음과 같습니다.
export const Wrapper = styled.div`
position: relative;
flex: 1;
`;
export const ContentsArea = styled.div`
position: absolute;
inset: 0;
overflow-y: auto;
`;
export const Blur = styled.div`
position: absolute;
bottom: 0;
width: 100%;
height: 100px;
background: linear-gradient(180deg, #fff0 0%, #fff 100%);
`;
type ScrollWithBlurProps = React.PropsWithChildren<{}>;
const ScrollWithBlur = ({ children }: WithBlurProps) => {
const { rootRef, targetRef, isOverflow } = useWithBlur();
return (
<Wrapper>
<ContentsArea ref={rootRef}>
<div ref={childrenRef}>
{children}
</div>
</ContentsArea>
{isOverflow &&
<Blur />
}
</Wrapper>
);
};
export default ScrollWithBlur;