본문 바로가기
  • 삽질하는 자의 블로그
메인-프로젝트/Next.js - 오늘 뭐먹지? 프로젝트

7. 모든 음식들을, 카테고리 별로, 태그 별로 검색되도록 구현하자

by 이게뭐당가 2022. 12. 2.

핵심 기능중 하나인 음식 페이지를 꾸며볼 차례입니다.

 

 음식들을

카테고리별 (한식,양식,중식 ... ),

태그별로(매움, 짭짤, 달달 ...)

로 구분지어 볼 수 있어야 했습니다.

 

주요한 기능이기에, "느린 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>&#5130; 스와이프하세요 &#5125; </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);
  }

끄읏

댓글