[React] 원하는 카테고리만 토글하여 보여주기

·2023년 11월 25일
0

React

목록 보기
5/8
post-thumbnail
  • 라이브러리 React + 상태관리 Zustand

  • 하고 싶었던 것 : 원하는 카테고리와 해당 아이템만 열고 닫기

  • 문제 발생 : 하나의 카테고리만 클릭해도 모든 카테고리가 동시에 열렸다!

도움 받은 게시글

영상을 업로드하는 어플리케이션으로, 원하는 카테고리(시리즈)를 설정하여 게시글을 작성할 수 있다.
카테고리(시리즈)는 이렇게 관리했다.

// categories.Js
export const categories = [
  { id: 1, name: 'Series_1' },
  { id: 2, name: 'Series_2' },
  { id: 3, name: 'Series_3' },
];
  • 기존 코드
import React, { useState, useEffect } from 'react';
import { categories } from 'api/categories';
import IconArrowDown from 'assets/img/icon-arrow-down.png';
import IconArrowUp from 'assets/img/icon-arrow-up.png';
import postStore from 'store/postStore';
import {
  UlSeries,
  CategorySeries,
  IconArrow,
  DivSeries,
  PostLi,
} from 'components/PostPortfolioUl/PostPortfolioUlStyle';

export default function PostPortfolioUl() {
  // useState 사용하여 토글 관리 
  const [toggle, setToggle] = useState(true);
  // 게시글 상태관리
  const allposts = postStore((state) => state.data);
  const callGetAPI = postStore((state) => state.getApi);

  useEffect(() => {
    callGetAPI();
  }, []);

    // 토글 핸들러
  const toggleHandler = () => {
    setToggle((prev) => !prev);
  };

  return (
    <>
      // map 이용해 카테고리(시리즈)명 보여주기
      {categories.map((series) => {
        return (
          <UlSeries>
            <CategorySeries>
              // 카테고리(시리즈)명 불러오기
              {series.name}
              // 토글시 펼치는<->닫히는 아이콘과 함께 카테고리 열고 닫기
              {toggle ? (
                <IconArrow
                  src={IconArrowUp}
                  alt='펼침'
                  onClick={toggleHandler}
                />
              ) : (
                <IconArrow
                  src={IconArrowDown}
                  alt='닫힘'
                  onClick={toggleHandler}
                />
              )}
            </CategorySeries>
              // 토글시 카테고리가 열리면서 카테고리에 맞는 아이템 보여주기
            <DivSeries style={{ display: toggle ? 'block' : 'none' }}>
              {allposts &&
                allposts
                  .slice(0)
                  .reverse()
                  .map((post, idx) =>
                    series.name === post.series ? (
                      <PostLi key={idx}>
                        <img src={post.thumnail} alt='영상 미리보기 이미지' />
                      </PostLi>
                    ) : null
                  )}
            </DivSeries>
          </UlSeries>
        );
      })}
    </>
  );
}
  • 개선 코드
import React, { useState, useEffect } from 'react';
import { categories } from 'api/categories';
import IconArrowDown from 'assets/img/icon-arrow-down.png';
import IconArrowUp from 'assets/img/icon-arrow-up.png';
import postStore from 'store/postStore';
import {
  ContPortfolio,
  UlSeries,
  CategorySeries,
  IconArrow,
  DivSeries,
  PostLi,
} from 'components/PostPortfolioUl/PostPortfolioUlStyle';

export default function PostPortfolioUl() {
  // 상태값 관리
  const [showItem, setShowItem] = useState([]);
  const allposts = postStore((state) => state.data);
  const callGetAPI = postStore((state) => state.getApi);

  useEffect(() => {
    callGetAPI();
  }, []);

  // 스프레드 연산자를 활용해 나머지 값은 저장
  // 파라미터로 받은 값을 key로 사용
  // 해당 값을 ! 활용해 true/false
  const toggleHandler = (id) => {
    setShowItem((prevShowItem) => ({
      ...prevShowItem,
      [id]: !prevShowItem[id],
    }));
  };

  return (
    <ContPortfolio>
      // map 활용해 카테고리 보여주기
      {categories.map((series) => {
        return (
          <UlSeries>
            <CategorySeries key={series.id}>
              {series.name}
			// 클릭시 토글 핸들러 함수 호출
           // 파라미터 값으로 key 전달
              {showItem[series.id] ? (
                <IconArrow
                  src={IconArrowUp}
                  alt='펼침'
                  onClick={() => toggleHandler(series.id)}
                />
              ) : (
                <IconArrow
                  src={IconArrowDown}
                  alt='닫힘'
                  onClick={() => toggleHandler(series.id)}
                />
              )}
            </CategorySeries>
            // showItem[series.id] 키 값이 true인 경우 해당 아이템 보여주기 (해당하지 않으면 null)
            <DivSeries
              style={{ display: showItem[series.id] ? 'block' : 'none' }}
            >
              {allposts &&
                allposts.slice(0).map((post, idx) =>
                  series.name === post.series ? (
                    <PostLi key={idx}>
                      <img src={post.thumnail} alt='영상 미리보기 이미지' />
                    </PostLi>
                  ) : null
                )}
            </DivSeries>
          </UlSeries>
        );
      })}
    </ContPortfolio>
  );
}

이렇게 원하는 카테고리와 해당 아이템만 열고 닫을 수 있게 되었다.
적용한 걸 이해하기 위해 포스팅해보았다!

profile
주니어 프론트엔드 웹 개발자 🐛

0개의 댓글