// 완성 예시
<Tabs>
<Tabs.Tab>Tab 1</Tabs.Tab>
<Tabs.Tab>Tab 2</Tabs.Tab>
<Tabs.Tab>Tab 3</Tabs.Tab>
<Tabs.TabPanel>Content for Tab 1</Tabs.TabPanel>
<Tabs.TabPanel>Content for Tab 2</Tabs.TabPanel>
<Tabs.TabPanel>Content for Tab 3</Tabs.TabPanel>
</Tabs>
먼저 프로젝트 구조를 설계합니다. 컴포넌트와 Context 파일을 분리합니다.
src/
components/
Tabs/
Tabs.js // 메인 Tabs 컴포넌트 (네임스페이스 정의)
Tab.js // Tab 컴포넌트
TabPanel.js // TabPanel 컴포넌트
TabContext.js // Tabs 상태 관리용 Context
TabContext.js는 Tabs 상태를 관리하기 위해 Context를 생성합니다.
// TabContext.js
import React, { createContext, useContext, useState } from "react";
const TabContext = createContext();
export const TabProvider = ({ children }) => {
const [activeIndex, setActiveIndex] = useState(0);
return (
<TabContext.Provider value={{ activeIndex, setActiveIndex }}>
{children}
</TabContext.Provider>
);
};
export const useTabContext = () => useContext(TabContext);
Tab.js는 개별 탭 버튼을 정의합니다. 클릭하면 해당 탭을 활성화합니다.
// Tab.js
import React from "react";
import { useTabContext } from "./TabContext";
const Tab = ({ children, index }) => {
const { activeIndex, setActiveIndex } = useTabContext();
return (
<button
onClick={() => setActiveIndex(index)}
style={{
fontWeight: activeIndex === index ? "bold" : "normal",
padding: "10px",
cursor: "pointer",
}}
>
{children}
</button>
);
};
export default Tab;
TabPanel.js는 각 탭의 콘텐츠를 렌더링합니다. 활성화된 탭에 해당하는 콘텐츠만 보입니다.
// TabPanel.js
import React from "react";
import { useTabContext } from "./TabContext";
const TabPanel = ({ children, index }) => {
const { activeIndex } = useTabContext();
if (activeIndex !== index) return null;
return <div style={{ padding: "10px" }}>{children}</div>;
};
export default TabPanel;
Tabs.js는 상위 컨테이너로, 네임스페이스를 정의하고 TabContext를 감싸 상태를 관리합니다.
// Tabs.js
import React from "react";
import { TabProvider } from "./TabContext";
import Tab from "./Tab";
import TabPanel from "./TabPanel";
const Tabs = ({ children }) => {
return <TabProvider>{children}</TabProvider>;
};
// 네임스페이스 구성
Tabs.Tab = Tab;
Tabs.TabPanel = TabPanel;
export default Tabs;
App.js에서 Tabs와 관련 컴포넌트를 사용합니다.
// App.js
import React from "react";
import Tabs from "./components/Tabs/Tabs";
const App = () => {
return (
<Tabs>
<Tabs.Tab index={0}>Tab 1</Tabs.Tab>
<Tabs.Tab index={1}>Tab 2</Tabs.Tab>
<Tabs.Tab index={2}>Tab 3</Tabs.Tab>
<Tabs.TabPanel index={0}>Content for Tab 1</Tabs.TabPanel>
<Tabs.TabPanel index={1}>Content for Tab 2</Tabs.TabPanel>
<Tabs.TabPanel index={2}>Content for Tab 3</Tabs.TabPanel>
</Tabs>
);
};
export default App;
Tabs는 상위 컴포넌트로 TabContext를 제공하고, 하위 컴포넌트를 네임스페이스로 관리합니다.
Tabs.Tab, Tabs.TabPanel로 하위 컴포넌트에 접근 가능합니다.
TabContext에서 현재 활성화된 탭(activeIndex)의 상태를 저장.
Tab 컴포넌트는 onClick으로 setActiveIndex를 호출하여 상태를 변경.
TabPanel은 activeIndex에 따라 해당 콘텐츠만 렌더링.
Tabs.Tab와 Tabs.TabPanel 처럼 사용하여 구조를 깔끔하게 유지.