대시보드 프로젝트에 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포커싱 기능에대해서 설명해볼게요!