선택된 탭과 페이지네이션 넘버를 쿼리값으로 받아서 탭 또는 페이지네이션 넘버가 바뀔 때마다 페이지 라우팅을 한다.
import { Fragment, useState, useCallback } from 'react';
import Image from 'next/image';
import { useRouter } from 'next/router';
import Footer from 'src/components/Common/Footer';
function UserBoardLog(props: any) {
const router = useRouter();
const { type } = props;
const { tab, page } = router.query;
const tabList = [
{ id: 'post', name: '내가 쓴 글' },
{ id: 'comment', name: '내가 쓴 댓글' },
{ id: 'like', name: '좋아요 한 글' },
];
const changeTab = useCallback(
(tab: string) => {
router.push({
pathname: '',
query: {
tab,
},
});
},
[tab],
);
const TabItem = (props) => {
const { key, onClick, active, name } = props;
return (
<div onClick={onClick} key={key} className={active ? 'active' : ''}>
{name}
</div>
);
};
return (
<>
<Fragment>
<div className="main-container" >
<div className="board-log container">
<div className="header">
<div className="back" onClick={(e) => router.back()}>
<Image src="/svg/LeftArrow.svg" width={22} height={19} />
</div>
<div className="title">내가 쓴 글</div>
</div>
<div className="tab">
{tabList.map((item, index) => (
<TabItem
key={index}
onClick={() => changeTab(item.id)}
active={item.id === tab}
name={item.name}
/>
))}
</div>
/* props.children 에 자식 컴포넌트들이 들어간다. */
<div className="body">{props.children}</div>
</div>
<Footer />
</div>
</Fragment>
</>
);
}
export default UserBoardLog;
생성한 레이아웃은 자식 컴포넌트의 layout
속성으로 선언해주면 끝!
/* pages/my/board.tsx */
import Image from 'next/image';
import { useRouter } from 'next/router';
import { useEffect, useState } from 'react';
import UserBoardLog from 'src/layouts/myboard';
import Pagination from 'src/components/Common/Pagination';
import Footer from 'src/components/Common/Footer';
const dummyPostData = [
{
title: '업비트 아하토큰 245개 에어드랍',
category: 'free',
publishTimestamp: '2021-06-11',
commentCount: 7,
},
{
title: '업비트 아하토큰 245개 에어드랍',
category: 'free',
publishTimestamp: '2021-06-11',
commentCount: 7,
},
];
const MyBoard = () => {
const router = useRouter();
const { tab, page } = router.query;
const [currentPage, setCurrentPage] = useState(1);
const [postPerPage] = useState(20);
const [Posts, setPosts] = useState<any[]>(dummyPostData);
const onChangePage = (page: number) => {
setCurrentPage(page);
router.replace(
{
query: {
tab,
page: page,
},
},
undefined,
{
shallow: false,
},
);
};
useEffect(() => {
// TODO: tab 또는 page가 바뀔 때마다 data fetch, setPosts 실행
window.scrollTo(0, 0);
}, [tab, page]);
const RenderedList = (query: any) => {
return Posts.map((el, index) => {
// 생략
}
};
return (
/* 게시물 리스트가 표시되는 영역으로, UserBoardLog 레이아웃 컴포넌트의 props.children 으로 들어간다. */
<>
<div className="list">{RenderedList(tab)}</div>
<Pagination
postPerPage={postPerPage}
totalPosts={Posts.length}
paginate={onChangePage}
currentPage={currentPage}
/>
</>
);
};
MyBoard.layout = UserBoardLog;
export default MyBoard;
사실 레이아웃 컴포넌트를 사용하려면, 미리 _app.tsx
에서 <Layout>
컴포넌트에 대한 선언을 해주어야한다. 이 부분은... 내가 좀 더 잘 설명할 수 있을 만큼 정확히 이해를 했을 때 글을 써봐야겠다.