리스트 아이템을 반복적으로 그리다 보면 마주치는 아주 큰 산이 하나 존재한다. 바로 아이템을 어떻게 정렬할 것인가를 생각하는 것이다.
아무 생각없이 아이템을 그냥 다 붙여넣다보면 이렇게 좌측으로 몰린 아이들을 만날 수 있다. 이게 마지막은 이렇게 나와야하는데 모든 리스트들이 이렇게 나오게 된다.
그럼 여기서 해결하는 가장 쉬운방법은 css로 이 리스트의 container div에 justify-content center를 주게 되면, 이 친구들은 정 가운데로 모이게 된다.
.campaignItemContainer {
width: 100%;
display: flex;
gap: 30px;
flex-wrap: wrap;
justify-content: center;
}
그럼 나머지 요소들이 아주 아름답게 가운데로 정렬된 걸 볼 수 있다.
물론 여기서 끝나면 서로 아름답게 끝나는 상황이다.
하지만 우리 css는 우리를 이렇게 쉽게 해결하도록 놔두지 않는다.
조금 더 내려가보면 한 친구가 안녕하면서 정 가운데에 위치하는 걸 볼수 있다. 그냥 지나치고 싶지만 이 아이를 그냥 지나쳤다간 계속해서 나를 따라오며 나는 어떻게 할 건데~ 라고 외칠 것 만 같다. 그럼.. 해결해보자.. 정말 여러가지 방법을 많이 써봤다. 마지막으로 사용할 방법을 안쓰기 위해서 그런데 다 실패했다. 어디엔간 이걸 다른 방법으로 해결한 천재들이 있겠지. 하지만 나는 결국 해내지 못 했다. 그냥 처음부터 이 방법을 쓸 걸 그랬다. 여러분에게도 다른 노력하지 말라고 마지막에 성공한 방법을 알려주도록 하겠다.
아주 간단하다. 브라우저 창의 크기를 인식하고, 브라우저 창의 크기가 얼마일때 5개가 정렬되어 있던 아이템들이 4개로 줄어드는지 체크하면된다.
우선 창의 사이즈가 변경될 때마다 창의 사이즈를 담아 반환하는 useWindowSize() 함수를 만듭니다.
// src/hooks/useWindowSize.js
import { useState, useEffect } from 'react';
function useWindowSize() {
// 초기 상태는 undefined로 설정하여 서버 사이드 렌더링 시 오류 방지
const [windowSize, setWindowSize] = useState({
width: undefined,
height: undefined,
});
useEffect(() => {
// 윈도우 크기 변경 핸들러
function handleResize() {
setWindowSize({
width: window.innerWidth,
height: window.innerHeight,
});
}
// 이벤트 리스너 추가
window.addEventListener('resize', handleResize);
// 초기 크기 설정
handleResize();
// 클린업: 컴포넌트 언마운트 시 이벤트 리스너 제거
return () => window.removeEventListener('resize', handleResize);
}, []); // 빈 배열을 의존성 배열로 설정하여 마운트와 언마운트 시에만 실행
return windowSize;
}
export default useWindowSize;
그리고 width를 가져오면서 브라우저의 넓이 별로 몇개의 컬럼이 들어가는지를 반환하는 함수를 하나 만들어줍니다.
const getColumns = (width) => {
if (width < 888) return 2;
if (width < 1194) return 3;
if (width < 1500) return 4;
return 5;
};
const Campaign = () => {
const [campaign, setCampaign] = useState(initialState);
const navigate = useNavigate();
const { width } = useWindowSize();
const baseItems = useMemo(() => {
const items = [
<CampaignItem
key={1}
campaign={campaign}
onClick={handleCampaignClick}
/>,
<CampaignItem key={2} campaign={campaign} />,
<CampaignItem key={3} campaign={campaign} />,
<CampaignItem key={4} campaign={campaign} />,
<CampaignItem key={5} campaign={campaign} />,
<CampaignItem key={6} campaign={campaign} />,
<CampaignItem key={7} campaign={campaign} />,
<CampaignItem key={8} campaign={campaign} />,
<CampaignItem key={9} campaign={campaign} />,
<CampaignItem key={10} campaign={campaign} />,
<CampaignItem key={11} campaign={campaign} />,
<CampaignItem key={12} campaign={campaign} />,
<CampaignItem key={13} campaign={campaign} />,
];
return items;
}, [campaign, handleCampaignClick]);
const finalItems = useMemo(() => {
const columns = getColumns(width);
const blankLength = baseItems.length % columns;
const blanksToAdd = blankLength === 0 ? 0 : columns - blankLength;
const blanks = [];
for (let i = 0; i < blanksToAdd; i++) {
blanks.push(<BlankItem key={`blank-${i}`} />);
}
return [...baseItems, ...blanks];
}, [baseItems, width]);
return (
<div className={styles.container}>
<CampaignSearch />
<div className={styles.campaignItemContainer}>{finalItems}</div>
</div>
);
};
그런 다음 공백 아이템을 만드는 함수를 하나 만들어주고, 리스트의 개수를 컬럼으로 나눠서 몇개의 공백 아이템이 들어갈지를 계산해서 추가해주면 완성입니다!
5개일때도,
4개일때도, 아주 잘 깔끔하고 이쁘게 작동되는걸 확인할 수 있습니다.
참 쉽죠? ^^
'IT Tech > React' 카테고리의 다른 글
이메일 Input 유효성 검사하기(Email Input Validate) (0) | 2024.10.29 |
---|---|
리액트(React), 컴포넌트(Component)에 대해서 (2) | 2024.09.07 |
React 프로젝트 스프링부트 프로젝트 안으로 빌드하기 (0) | 2024.07.29 |
스프링 프로젝트 안에 리액트(React) 프로젝트 생성하기 (0) | 2024.07.29 |
JavaScript Fetch와 Spring Boot에서 URL 경로 포함한 DELETE 요청 처리 방법 (0) | 2024.07.11 |