[리팩토링] overFlow를 감지해 정렬 바꾸기

yoon Y·2022년 3월 9일
0

[2nd_Project] WaffleCard

목록 보기
11/15

요구사항

  • 메인 페이지의 카드 리스트 정렬이 카드갯수에 따라 달라져야함
  • 스크롤이 생기면 왼쪽 정렬, 스크롤이 안 생기면 가운데 정렬이 되어야함
  • 탭을 이동해도 적용되어야 함

구현 방법

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'};
  ...
`;
profile
#프론트엔드

0개의 댓글