만두의 부트캠프 🤔
  • [Day4] 4-3. CategoryTab 만들기
    2023년 12월 17일 09시 28분 26초에 업로드 된 글입니다.
    작성자: 만두33

     

    이번에는 CategoryTab을 만들것이다.

    메인 제일 위, 이전에 만든 CategoryBox위에 위치하게 한다.

    CategoryTab은 화면이 전환되어도 고정되어 있어야한다.

    CategoryTab도 서버에서 받아오는것이다.

    CategoryTab안의 Tab요소들도 각각의 컴포넌트로 분리해서 클릭했을때 효과를 부여한다.


    # CategoryTab.jsx 초반코드

    ✔️ CategoryTab.jsx 만들기

    components안에 만들어준다.

    기본코드 입력해준다.

    export default function CategoryTab () {
        return <div>CategoryTab</div>;
    }

     

    ✔️ MainPage.jsx

    import CategoryTab from '../components/CategoryTab';
    ...
      return (
        <main>
          <section ClassName = "main_container">
            <CategoryTab/>
            <CategoryBox items={items} />
          </section>
        </main>
      );
    }

    메인안에 섹션으로 카테고리탭과 카테고리 박스를 묶어준다.

    그리고 main_container라는 클래스네임을 정해준다.

    카테고리탭이 나타나는 모습!

     


    # CategoryTab.jsx 코드

    여러 코드를 참고하면서 만드니까.. 오류가 너무 너무 많이났다..🫠

    레퍼코드를 보고 고치고 적용하고는 한 612345번 정도 반복한 결과...

    서버에서 데이터로 카테고리 받아오기 성공 ❗️👏

    코드가 길지만 일단 다 적어놓기

     

    ✔️ MainPage.jsx 코드

    // MainPage.jsx
    import React, { useState, useEffect } from 'react';
    import { fetchData } from '../apiService';
    import CategoryBox from '../components/CategoryBox';
    import CategoryTab from '../components/CategoryTab';
    import ItemSlider from '../components/ItemSlider';
    import { API_URL } from '../constants';
    import useFetch from "../useFetch";
    
    export default function MainPage() {
      const [items, setItems] = useState([]);
      const [selectedId, setSelectedId] = useState(null);
      // const [selectedCategoryId, setSelectedCategoryId] = useState(0);
      const [categories, setCategories] = useFetch("/categories");
      const [rankingItems, setRankingItems] = useFetch("/ranking");
    
      useEffect(()=> {
        fetchData('categories').then((data) => setCategories(data));
    
      })
      useEffect(() => {
        setItems([]);
        fetchData(
          `/products?limit=12&${
            selectedId > 0 ? `category=${selectedId}` : ""
          }`,
        ).then((data) => setItems(data.items));
      }, [selectedId]);
    
    
    
      return (
        <main>
          <section className="main_container">
              {categories && (
                <CategoryTab
                  categories={categories}
                  selectedId={selectedId}
                  setSelectedId={setSelectedId} 
                />
                )}
            <CategoryBox items={items} />
            </section>
            {items && <ItemSlider title = {"랭킹별 아이템"} rankingItems={items.items} />}
        </main>
      );
    }

     

    ✔️ CategoryTab.jsx

    //CategoryTab.jsx
    export default function CategoryTab({ categories, setSelectedId }) {
      return (
        <div className="category_tab">
          {[<span key={0} onClick={() => setSelectedId(0)}>홈</span>]}
          {categories?.product?.map((category) => (
            <div key={category.id} onClick={() => setSelectedId(category.id)}>
              <span>{category.title}</span>
            </div>
          ))}
        </div>
      );
    }

    ✔️ App.css

    제일 아래부분에 그냥 적으면됨

    ...
    .category_tab{
      width : 30%;
      flex-shrink: 0;
      display: flex;
      flex-direction: row;
      align-items: center;
      border: 2px solid green;
      justify-content: space-between;
      font-size: 30px;
      padding : 16px;
      margin: 20px auto; /* auto를 해주면 화면 중앙에 위치한다.*/
    }

     

    그리고 

    ✔️ useFetch.js

    레퍼코드에서 useFetch.js를 따로 분리하니까 메인 코드도 한결 깔끔해져서

    일단 나도 가져왔다.

    import { useState, useEffect } from 'react';
    import { fetchData } from '../src/apiService';
    
    function useFetch(url, deps = []) {
      const [data, setData] = useState(null);
      const [loading, setLoading] = useState(true);
    
      useEffect(() => {
        setLoading(true);
        fetchData(url).then((result) => {
          setData(result);
          setLoading(false);
        });
        // eslint-disable-next-line react-hooks/exhaustive-deps
      }, deps);
    
      return [data, loading];
    }

     

     

    * 코드 설명

    더보기

    이 코드는 React에서 사용하는 커스텀 훅 중 하나로, 비동기적으로 데이터를 가져오기 위한 것입니다.
    이 훅은 주어진 URL에서 데이터를 가져오고 해당 데이터를 상태로 관리하며,
    데이터가 로딩 중인지 아닌지를 추적하는 데 사용됩니다.

    여러 가지 개념을 살펴보겠습니다:

    1. useState:
      useState 함수는 React에서 상태를 추가하는 데 사용됩니다.
      여기서는 data와 loading이라는 두 가지 상태를 정의합니다.
      data는 가져온 데이터를 저장하고, loading은 데이터가 로딩 중인지 여부를 나타냅니다.

    2. useEffect:
      useEffect 훅은 컴포넌트의 생명주기에 특정한 부작용(예: 데이터 가져오기, 구독 설정 등)을 수행하기 위해 사용됩니다.
      이 훅은 컴포넌트가 마운트될 때와 deps 배열에 지정된 의존성이 변경될 때마다 실행됩니다.

    3. fetchData 함수:
      이 훅에서 사용된 fetchData 함수는 주어진 URL에서 데이터를 가져오는 비동기 함수로 가정합니다.
      이 함수는 Promise를 반환합니다.

    4. deps 배열: useEffect의 두 번째 인자로 전달된 deps 배열은 해당 훅이 의존하는 값들을 포함하고 있습니다.
      이 값들 중 하나라도 변경되면 useEffect 내의 코드 블록이 실행됩니다.

    5. 로딩 상태 변경:
      데이터를 가져오는 동안 로딩 상태를 true로 설정하고, 데이터를 가져오면 로딩 상태를 false로 설정합니다.

    6. 반환 값:
      useFetch 함수는 [data, loading] 배열을 반환합니다.
      이 배열은 컴포넌트에서 해당 훅을 사용할 때 구조 분해(destructuring)하여 사용됩니다.
      data에는 가져온 데이터가, loading에는 데이터가 로딩 중인지 여부가 포함됩니다.

    예를 들어, 컴포넌트에서 이 훅을 사용하면 다음과 같이 사용할 수 있습니다:

    const [userData, isLoading] = useFetch('/user/123');

    이렇게 하면 userData에는 사용자 데이터가, isLoading에는 데이터가 로딩 중인지 여부가 담기게 됩니다.


    # CategoryTab 컴포넌트로 분리

    카테고리 탭을 하나하나 분리해서

    누를때마다 글자 색이 바뀌는 효과를 준다.

    // CategoryTab.jsx
    const TabItem = ({ onClick, title, imageUrl, isActive }) => {
      return (
        <div className="tab_item" onClick={onClick}>
          <span style={{ color: isActive ? '#2c01b8' : 'black' }}>{title}</span>
        </div>
      );
    };
    
    export default function CategoryTab({ categories, setSelectedId, selectedId }) {
      return (
        <div className="category_tab">
          <TabItem
            onClick={() => setSelectedId(null)}
            title="홈"
            isActive={selectedId === null}
          />
          {categories?.product?.map((category) => (
            <TabItem
              key={category.id}
              onClick={() => setSelectedId(category.id)}
              title={category.title}
              isActive={selectedId === category.id}
            />
          ))}
        </div>
      );
    }

     

    탭을 누를때마다 해당 탭의 컬러가 바뀐다!! 

    댓글