[Next.js 블로그] 데이터 컨트롤러. 카드 수량 제어
getCardData controller를 만들어서. 데이터 종류를 추출해 한 페이지 당 보여주는 카드의 수량을 제한해 보기
기존 진행된 내용
이전 참고 내용
[카드 리스트 기본틀]
[카드 리스트 grid]
[한자 카드]
[블로그 카드]
[블로그 카드 이미지]
[페이지별 다른 카드 리스트]
/cantonese
한자 페이지/cantonese/word
단어 페이지/blog
블로그 페이지
3개 페이지에서 CardList
를 사용했다.
각 페이지에서 타입과 데이터를 전달해서CardList
에서 grid 디자인을 조절하고,CnCard
와 BlogCard
를 선택했다.
이번 계획
한 페이지에 카드의 수량을 제한하고 싶다.
controller
폴더를 따로 만들어서getCardData.js
를 생성해서
보여줄 카드를 제어할 계획이다.
제어할 내용은
데이터의 종류와 수량이다.
이번 관련된 내용
- javascript 배열 sort() 함수
- javascript 배열 filter() 함수
- javascript 배열 slice() 함수
- javascript 남은 수 % 연산
getCardData 만들기
getCardData.js 파일 생성
// .\app\controller\getCardData.js
export function getCardData() {
return [];
}
export
내보내기를 해야
다른 곳에서 사용할 수 있다.
기능 계획
/cantonese/page.js
한자 페이지/cantonese/word/page.js
단어 페이지/blog/page.js
블로그 페이지
CardList
와 동일하게 위 3개 페이지에서 사용될 것이다.
필요한 내용(변수)은
- 데이터
- 현재 페이지
- 한 페이지 최대 카드 수량
- 현재 태그 ( SubNav 내용 [서브nav 편]참고 )
데이터에서 카테고리를 구분해서
필요한 페이지의 카드를
최대 수량만큼 return 할 생각이다.
기능 구현
방법이 여러개 생각난다.getCardData
에서 전부 처리하는 방법,
데이터를 전달하는 방법,
데이터의 해당 카테고리만 분리해서 전달하는 방법...
하지만 우선 기능은 같기 때문에
하나로 작성하기로 했다.
// .\app\controller\getCardData.js
export function getCardData(category, pageNum, maxCardInPage) {
const data = getCategoryData(category);
const dataLength = data.length;
const isFullCard = dataLength - pageNum * maxCardInPage >= 0;
const cardLength = isFullCard ? maxCardInPage : dataLength % maxCardInPage;
const startCardNum = (pageNum - 1) * maxCardInPage;
const endCardNum = startCardNum + cardLength;
return data.slice(startCardNum, endCardNum);
}
function getCategoryData(category) {
if (category == "tc") return getTcData();
if (category == "word") return getWordData();
if (category == null) {
return getBlogData()
} else{
return getBlogData().filter((post) => post.category == category)
}
}
function getBlogData() {
const tempBlog = [
{ date: "2024-01-01 00:00:00", category: "coding" title: "1", desc: "설명1", slug: "1" },
{ date: "2024-01-02 00:00:00", category: "coding" title: "2", desc: "설명2", slug: "2" },
{ date: "2024-01-03 00:00:00", category: "coding" title: "3", desc: "설명3", slug: "3" },
{ date: "2024-01-04 00:00:00", category: "cantonese" title: "4", desc: "설명4", slug: "4" },
{ date: "2024-01-05 00:00:00", category: "cantonese" title: "5", desc: "설명5", slug: "5" },
{ date: "2024-01-06 00:00:00", category: "cantonese" title: "6", desc: "설명6", slug: "6" },
{ date: "2024-01-07 00:00:00", category: "daily" title: "7", desc: "설명7", slug: "7" },
{ date: "2024-01-08 00:00:00", category: "daily" title: "8", desc: "설명8", slug: "8" },
{ date: "2024-01-09 00:00:00", category: "daily" title: "9", desc: "설명9", slug: "9" },
];
return tempBlog.sort((a,b) => b.date - a.date);
}
예시getCardData
getCategoryData
getBlogData
5개의 함수를 만들었다.
(getTcData, getWordData 생략)
getCardData
을 외부에서 사용할 것이고,
다른 함수들은 getCardData
내부에서 사용될 것이다.
getCategoryData
은 간단하다.category
를 체크하고 데이터를 get한다.
getCategoryData: 배열 sort 함수
// .\app\controller\getCardData.js - getCategoryData
function getBlogData() {
const tempBlog = [
...
];
return tempBlog.sort((a,b) => b.date - a.date);
}
아직 DB결정을 하지 않고
getter를 만들지 않아서...getBlogData
함수를 만들어서
전에 만들었던 임시 데이터를 사용했다.
sort
함수를 사용해서 최신순으로 정열해서 return 했다.
getBlogData: 배열 filter 함수
// .\app\controller\getCardData.js - getCategoryData
function getCategoryData(category) {
if (category == "tc") return getTcData();
if (category == "word") return getWordData();
if (category == null) {
return getBlogData();
} else {
return getBlogData().filter((post) => post.category == category);
}
}
getCategoryData
함수는 category
를 받는다.category
를 체크해서 다른 get함수를 호출한다.
blog 데이터의 경우, 카테고리가 있으면
filter를 사용해서 해당 내용만 return했다.
getCardData: 배열 slide 함수
// .\app\controller\getCardData.js - getCardData
export function getCardData(category, pageNum, maxCardInPage) {
const data = getCategoryData(category);
const dataLength = data.length;
const isFullCard = dataLength - pageNum * maxCardInPage >= 0;
const cardLength = isFullCard ? maxCardInPage : dataLength % maxCardInPage;
const startCardNum = (pageNum - 1) * maxCardInPage;
const endCardNum = startCardNum + cardLength;
return data.slice(startCardNum, endCardNum);
}
현 카테고리 : category
,
현재 페이지 : pageNum
,
최대 카드수 : maxCardInPage
을 받는 함수이다.
const data = getCategoryData(category);
getCategoryData
를 호출해서
해당 카테고리의 데이터를 받았다.
const dataLength = data.length;
해당 데이터의 길이를 보고
const isFullCard = dataLength >= pageNum * maxCardInPage;
const cardLength = isFullCard ? maxCardInPage : dataLength % maxCardInPage;
현재 페이지에 남은 카드의 수량이 최대 카드수량 만큼 있는지 확인하고...
참이면 최대 카드수를, 거짓이면 남은 수량을 확인했다.
const startCardNum = (pageNum - 1) * maxCardInPage;
const endCardNum = startCardNum + cardLength;
배열 시작과 끝을 확인하고
return data.slice(startCardNum, endCardNum);
해당되는 데이터를 전달했다.
결과보기
Blog 페이지에 적용하기
import Heros from "./components/Heros";
import SubNav from "./components/SubNav";
import CardList from "./components/CardList";
import { getCardData } from "./controller/getCardData";
export default function Blog(props) {
const tag = props.searchParams.tag; // SubNav 편에서 만들음
const page = props.searchParams.page ?? 1;
const maxCardInPage = 6;
const blogData = getCardData(tag, page, maxCardInPage);
return (
<>
<Heros path="blog" />
<SubNav path="blog" slug={tag ?? ""} />
<CardList path="blog" data={blogData} />
</>
);
}
- [SubNav편]에서 만들었던 props를 사용해서
tag
와page
를 확인한다. page
는 없는 경우 1로 사용했다.maxCardInPage
는 6으로 설정했다. (6개/페이지)getCardData
로 데이터를 받았다.
결과
원하는 결과가 나온다.
지금 임시 데이터는 모두 9개이지만maxCardInPage
인 6개만 나온다.
SubNav로 다른 태그를 클릭하면
각 3개도 잘 나온다.
하지만 아직 pagination이 없어서 페이지를 이동할 수 없다.
우선 테스트를 위해서 브라우저 주소로 ?page=2
를 사용했다.
전체링크 : http://localhost:3000/cantonese?page=2
이도 남은 3개의 카드가 잘 나온다.