핵심 기능중 하나인 음식 페이지를 꾸며볼 차례입니다.
음식들을
카테고리별 (한식,양식,중식 ... ),
태그별로(매움, 짭짤, 달달 ...)
로 구분지어 볼 수 있어야 했습니다.
주요한 기능이기에, "느린 UX 보다는, 빠른 UX 가 필요했습니다."
로딩은 조금 있을지언정, 좋은 유저경험을 위해 getStaticProps 로 "사전 데이터 페칭을 진행했습니다"
1. AllFoodsPage 에, 사전 데이터 페칭을 해줍니다.
페칭된 데이터들을 음식들이 있는 컴포넌트로, 넘겨줍니다.
import FoodCategoryHeader from "../../components/food-components/food-category-header";
import { connectDb, findAllFoods } from "../../helper/db-util";
import Head from "next/head";
function AllFoodsPage(props) {
const { allfoods } = props;
return (
<div>
<Head>
<title> All Foods with Category</title>
<meta name="description" content="this show all foods with category" />
</Head>
{<FoodCategoryHeader foodData={allfoods} />}
</div>
);
}
export async function getStaticProps() {
const client = await connectDb();
const allFoods = await findAllFoods(client);
const arrangeAllFoods = allFoods.sort((A, B) => (A.name > B.name ? 1 : -1));
return {
// 직렬화 문제로 인해, 두번 변환해서 사용
props: { allfoods: JSON.parse(JSON.stringify(arrangeAllFoods)) },
};
}
export default AllFoodsPage;
* Array.sort() 를 통해, 이름순으로, 정리하여 넣어줍니다.
2. Food를 보여줄 컴포넌트를 만들어, FoodData 를 받고, filter 를 통해,
버튼을 누르면, 필요한 데이터만 보이게 만들어줍니다.
import { Swiper, SwiperSlide } from "swiper/react";
import "swiper/css";
import FoodList from "./food-list";
import styles from "./food-category-header.module.css";
import { useState, useEffect } from "react";
// 카테고리 누르면, Allfoods-page 에서 온 Data 들을, filter 처리 해서, Food-list-component 로 보내줌
// All 을 누르면, Allfoods-page 에서 온 Data들을, filter 처리 없이, Food-list-component 로 보내줌
function FoodCategoryHeader(props) {
const { foodData } = props;
const [insertFoodData, setInsertFoodData] = useState(foodData);
// 버튼 누르면, food 선별작업 해서, 새로운 데이터를 만든 후, Foodlist 로 넘겨준다.
function foodFilter(category) {
const filteredFoods = foodData.filter((food) => food.category === category);
setInsertFoodData(filteredFoods);
}
function fansyFilter() {
const filteredFoods = foodData.filter((food) => food.fansy == "true");
setInsertFoodData(filteredFoods);
}
return (
<div className={styles.maindiv}>
<header className={styles.header}>
<Swiper spaceBetween={23} slidesPerView={6}>
<SwiperSlide>
<li onClick={() => setInsertFoodData(foodData)}>전체</li>
</SwiperSlide>
<SwiperSlide>
<li onClick={() => foodFilter("다이어트")}>식이</li>
</SwiperSlide>
....
<SwiperSlide>
<li onClick={() => foodFilter("디저트")}> 디저트 </li>
</SwiperSlide>
<SwiperSlide>
<li onClick={() => fansyFilter()}> 고급 </li>
</SwiperSlide>
<SwiperSlide>
<li> </li>
</SwiperSlide>
</Swiper>
<p>ᐊ 스와이프하세요 ᐅ </p>
</header>
<main>
<FoodList foodData={insertFoodData} />
</main>
</div>
);
}
export default FoodCategoryHeader;
카테고리를 누르면, foodFilter 함수가 호출되어, 콜백형태로 실행되게 만들어줍니다.
React 는 onClick={함수이름} 으로, 인수 없이 함수를 호출해야, 평가된 함수가,
이벤트 리스너에 반응해 실행을 하게 됩니다.
onClick={foodFilter("다이어트")} 처럼 쓰게 되면, 이는 "함수가 바로 실행" 되므로, 콜백 형태로 적어준 것입니다.
이렇게 하면!
이렇게 적용된다!

3. 태그별에는 filter 의 조건에, includes() 를 사용하여
여러가지 태그중 하나만 들어 있어도 필터링이 되게만듭니다.
function FoodTagsHeader(props) {
const { foodData } = props;
const sortedFoodData = foodData.sort((A, B) => (A.name > B.name ? 1 : -1));
const [insertFoodData, setInsertFoodData] = useState(foodData);
// 버튼 누르면, food 선별작업 해서, 새로운 데이터를 만든 후, Foodlist 로 넘겨준다.
// 태그가 하나라도 포함되어있으면, 보여준다.
function foodFilter(taste) {
const filteredFoods = foodData.filter((food) => food.taste.includes(taste));
setInsertFoodData(filteredFoods);
}
끄읏

'메인-프로젝트 > Next.js - 오늘 뭐먹지? 프로젝트' 카테고리의 다른 글
9. 개인 유저 별 찜 기능을 구현해보자 (0) | 2022.12.03 |
---|---|
8. 칼로리 계산기를 만들어보자. with DOM (0) | 2022.12.03 |
6. 로그인 기능 구현 with Next-Auth (0) | 2022.12.02 |
0. 내가 React, Nextjs 를 선택한 이유 (0) | 2022.12.02 |
5. DB 연결 with. MongoDB Atlas 그리고 API (0) | 2022.12.02 |
댓글