scrollWidth, clientWidth(ref로 접근)를 사용해 자식의 너비가 부모의 것보다 클 때(스크롤이 생길 때) 상태를 true로 바꿔주고, 그 상태를 기준으로 카드리스트 컴포넌트의 flex정렬 속성을 동적으로 바꿔준다.
처음 카드가 렌더링 될 때, Tab이 바뀔 때 정렬을 다시해야하므로 의존성으로 TabName상태를 걸어줬다
// useIsOverflow.js
import React, { useLayoutEffect } from 'react';
const useIsOverflow = (element, tabName) => {
const [isOverflow, setIsOverflow] = React.useState(false);
useLayoutEffect(() => {
const trigger = () => {
const hasOverflow = element.scrollWidth > element.clientWidth;
console.log('trigger', element);
setIsOverflow(hasOverflow);
};
if (element) {
trigger();
}
}, [tabName, element]);
return isOverflow;
};
export default useIsOverflow;
Tab을 이동할 때마다 카드의 갯수가 달라질 수 있기 때문에 (ex-오늘의 카드, 관심 카드의 갯수가 다를 수 있다) Tab이동 시마다 useIsOverflow가 실행되도록 tabName을 의존성으로 걸어줬었다
하지만 현재의 isOverflow값이 전 tab에 렌더링된 카드리스트의 너비로 판단되어 제대로 동작하지 않았다
카드들이 다 렌더링되기 전의 값을 가져오기 때문이다
의존성을 카드리스트의 scrollWidth로 걸어줘야 카드가 그려지고 나서의 길이를 가져와서,
카드갯수가 달라질 때마다 isOverflow가 실행되어 제대로 동작할 수 있었다
// useIsOverflow.ts
const useIsOverflow = <T extends HTMLElement = HTMLElement>(): [
React.RefObject<T>,
boolean,
] => {
const [isOverflow, setIsOverflow] = useState<boolean>(false);
const ref = useRef<T>(null);
const scrollWidth = ref.current?.scrollWidth;
useEffect(() => {
const element = ref.current;
if (element) {
const isOverflow = element.scrollWidth > element.clientWidth;
setIsOverflow(isOverflow);
}
}, [scrollWidth]);
return [ref, isOverflow];
};
// WaffleCardList.tsx
const Container = styled.article<{
isOverflow: boolean;
type?: 'total' | 'my' | 'like';
}>`
${({ type }) => {
if (type === 'my') {
return css`
display: flex;
justify-content: center;
align-items: center;
`;
}
}}
display: flex;
justify-content: ${({ isOverflow }) =>
isOverflow ? 'flex-start' : 'center'};
...
`;