react-tabs 동적으로 사용하기

SuweonPark·2023년 11월 21일
1

대시보드

목록 보기
1/5

대시보드 프로젝트에 tabPage 기능이 필요했는데
이때 적용했던 react-tabs의 탭을 동적으로 사용하기 위해
사용했던 방법에 대해 설명해보려고 합니다!
결론은 useEffect 리액트 훅에 의존성배열을 잘 활용하자! 입니다.
제가 이 라이브러리를 도입한 이유는 tabIndex를 통해 사용자가
어떤 탭을 포커싱 할 건지 컨트롤 할 수 있는 기능이 있었기 때문입니다.
나중에 제가 만들 검색기능에 활용하기 위해서였죠
라이브러리: react-tabs

코드를 보면서 설명해볼게요

 useEffect(() => {
 // 탭 페이지를 생성하기 위한 함수
    siteTitleListHanlder();
 }, [userPagesData]);

먼저 useEffect를 사용해 siteTitleListHanlder(); 탭 페이지를 생성하기 위한 함수를 넣어주고 useEffect의 의존성 배열에 userPagesData를 넣어줬습니다.

const userPagesData = useRecoilValue(UserPageOpen);
const [tabs, setTabs] = useState([]);
const [tabTitle, setTabTitle] = useState([]);

  const siteTitleListHanlder = () => {
    const regionTitleList = [];
    const newTabs = [];
    userPagesData?.forEach(item => {
      regionTitleList.push(item.pageName);
    });

    const updatedTitleList = ['전국 현황', ...regionTitleList];

    for (let i = 0; i < updatedTitleList.length; i++) {
      const tabTitleItem = updatedTitleList[i];

      // 탭 생성 및 추가
      let newTab;
      if (tabTitleItem === '전국 현황') {
        newTab = {
          title: '전국 현황',
          pageId: 0,
          content: <NationSite />,
        };
      } else {
        newTab = {
          title: tabTitleItem,
          pageId: userPagesData?.[i - 1]?.pageId,
          content: (
            <WidgetLayout
              pageInfo={userPagesData?.[i - 1]}
              tabTitleItem={tabTitleItem}
            />
          ),
        };
      }
      newTabs.push(newTab);
    }
    setTabs(newTabs); // 새로운 상태값으로 설정
    setTabTitle(updatedTitleList);
  };

이 함수에서 사용되는 userPagesData는 서버를 통해 받아온 해당 유저의
탭페이지 정보입니다. 저는 미리 데이터를 받아와서 recoil 라이브러리를 사용해
전역 변수로 저장하고 사용했습니다.
간단하게 이 함수에 대해서 설명하자면 서버에 저장된 데이터를 가지고
각 tab에 필요한 정보를 넘겨주고 마지막으로 tabs에 데이터를 저장하기위한 함수 입니다.

<Tabs
  className={isMobile() ? '' : 'onDeskTop'}
  selectedIndex={tabIndex === undefined ? 0 : tabIndex}
  onSelect={index => onSelectHandler(index)}
 >
 {tabs.map((tab, index) => (
  	<TabPanel className="container react-tabs__tab-panel" key={index}>
       {tab.content}
  	</TabPanel>
    ))}
</Tabs>

tab에 저장된 데이터를 가지고 map 함수를 돌려주면
서버에서 가져온 데이터가 화면에 잘 렌더링이 됩니다.
여기서 탭을 추가하거나 삭제하고 싶다면 앞서 설명한

 useEffect(() => {
 // 탭 페이지를 생성하기 위한 함수
    siteTitleListHanlder();
 }, [userPagesData]);

useEffect 리액트 훅에 의존성 배열에 있는 userPagesData값에 변화를 주면
됩니다. 해당 값이 변하면 siteTitleListHandlder() 함수를 실행해
필요한 데이터를 업데이트 할테니까요.

전체코드

import React, { useState, useRef, useEffect } from 'react';
import { Tab, Tabs, TabList, TabPanel } from 'react-tabs';
import { useRecoilState, useRecoilValue } from 'recoil';
import WidgetLayout from '../../../components/WidgetLayout/WidgetLayout';
import NationSite from '../../../components/WidgetLayout/NationSite';
import { SiteListModal, SiteManageModal } from '../../../components/modal';
import { UserPageOpen } from '../../../recoil/atom';

const TabPage = ({ setSideModalState }) => {
const userPagesData = useRecoilValue(UserPageOpen);
  const [tabs, setTabs] = useState([]);
  const [tabTitle, setTabTitle] = useState([]);
  const [tabIndex, setTabIndex] = useRecoilState(TabIndexState);

  const siteTitleListHanlder = () => {
    const regionTitleList = [];
    const newTabs = [];
    userPagesData?.forEach(item => {
      regionTitleList.push(item.pageName);
    });

    const updatedTitleList = ['전국 현황', ...regionTitleList];

    for (let i = 0; i < updatedTitleList.length; i++) {
      const tabTitleItem = updatedTitleList[i];

      // 탭 생성 및 추가
      let newTab;
      if (tabTitleItem === '전국 현황') {
        newTab = {
          title: '전국 현황',
          pageId: 0,
          content: <NationSite />,
        };
      } else {
        newTab = {
          title: tabTitleItem,
          pageId: userPagesData?.[i - 1]?.pageId,
          content: (
            <WidgetLayout
              pageInfo={userPagesData?.[i - 1]}
              tabTitleItem={tabTitleItem}
            />
          ),
        };
      }
      newTabs.push(newTab);
    }
    setTabs(newTabs); // 새로운 상태값으로 설정
    setTabTitle(updatedTitleList);
  };

  useEffect(() => {
    siteTitleListHanlder();
  }, [userPagesData]);

  return (
    <>
      <div className="layout_right">
        <Tabs
          selectedIndex={tabIndex === undefined ? 0 : tabIndex}
          onSelect={index => onSelectHandler(index)}
        >
          {tabs.map((tab, index) => (
            // eslint-disable-next-line react/no-array-index-key
            <TabPanel className="container react-tabs__tab-panel" key={index}>
              {tab.content}
            </TabPanel>
          ))}
        </Tabs>
      </div>
    </>
  );
};

export default React.memo(TabPage);

다음글에서는 검색기능을 이용한 react-tabs포커싱 기능에대해서 설명해볼게요!

profile
프론트엔드 개발자

0개의 댓글