[React] 네임스페이스를 사용한 컴포넌트

JIOO·2025년 1월 14일
0

React

목록 보기
19/19

🧑🏻‍💻 목표

  1. Tabs 컴포넌트와 Tab, TabPanel 같은 하위 컴포넌트를 각각의 파일에 분리.
  2. 네임스페이스 패턴(Tabs.Tab, Tabs.TabPanel)을 사용하여 코드 구조를 명확히 정리.
  3. 최종적으로 사용자는 다음처럼 간단히 사용할 수 있게 만들기
// 완성 예시

<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>

1. 파일 구조

먼저 프로젝트 구조를 설계합니다. 컴포넌트와 Context 파일을 분리합니다.

src/
  components/
    Tabs/
      Tabs.js         // 메인 Tabs 컴포넌트 (네임스페이스 정의)
      Tab.js          // Tab 컴포넌트
      TabPanel.js     // TabPanel 컴포넌트
      TabContext.js   // Tabs 상태 관리용 Context

2. Tabs 상태 관리: TabContext.js

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);

3. Tab 컴포넌트: Tab.js

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;

4. TabPanel 컴포넌트: TabPanel.js

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;

5. Tabs 메인 컴포넌트: Tabs.js

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;

6. App 컴포넌트: 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가 네임스페이스 역할:

Tabs는 상위 컴포넌트로 TabContext를 제공하고, 하위 컴포넌트를 네임스페이스로 관리합니다.
Tabs.Tab, Tabs.TabPanel로 하위 컴포넌트에 접근 가능합니다.

Context로 상태 관리:

TabContext에서 현재 활성화된 탭(activeIndex)의 상태를 저장.
Tab 컴포넌트는 onClick으로 setActiveIndex를 호출하여 상태를 변경.
TabPanel은 activeIndex에 따라 해당 콘텐츠만 렌더링.

사용자는 네임스페이스로 접근:

Tabs.Tab와 Tabs.TabPanel 처럼 사용하여 구조를 깔끔하게 유지.

profile
프론트엔드가 좋은 웹쟁이

0개의 댓글