
마이페이지 UI를 구성하면서, 탭 기능을 간단하게 구현해봤다.
처음에는 useState를 컴포넌트 내부에 직접 선언해서 관리했지만, 재사용성과 가독성을 높이기 위해
공통 로직을 커스텀 훅 useTabs로 분리했다.
const tabs = ['내 정보', '내 포스트', '좋아요'];
const [activeTab, setActiveTab] = useState(0);
<div className="flex w-auto border-b md:w-80">
{tabs.map((tab, index) => {
return (
<button
key={index}
onClick={() => setActiveTab(index)}
className={`flex-1 p-2 text-center ${
activeTab === index ? 'border-b-2 border-gray-500 font-semibold' : 'text-gray-500'
}`}
>
{tab}
</button>
);
})}
</div>
<div className="flex flex-col items-center justify-center w-full p-4">
{activeTab === 0 && <MyInfo />}
{activeTab === 1 && <MyPost />}
{activeTab === 2 && <MyStatus />}
</div>
tabs 배열에 탭 이름을 정의하고, useState(0)으로 기본 탭을 설정했다.
이후 activeTab의 값에 따라 각 컴포넌트를 조건부 렌더링하는 방식으로 구성했다. 이런 방식은 단순하지만 직관적이고 유지보수도 편함.
activeTab === index ? 삼항 연산자를 통한 클래스 또한 분기하여 selected 상태일 때를 표시
import { useState } from 'react';
export const useTabs = (initialIndex = 0) => {
const [index, setIndex] = useState(initialIndex);
const changeTab = (i) => setIndex(i);
return { index, changeTab };
};
hooks 폴더에 useTabs.js로 추출하여 재사용성과 가독성을 높인 훅
초기값을 initailIndex = 0 으로 설정해 두어 호출시 원하는 탭 번호로 인덱스를 바꿀 예정
객체(Object)로 리턴하여 {index: 현재 선택된 탭 번호 (state), changeTab: 탭을 바꾸는 함수 (함수)} 로구조분해 할당을 하기 위한 전처리
import { useTabs } from '../hooks/useTabs';
const tabs = ['내 정보', '내 포스트', '좋아요'];
const { index, changeTab } = useTabs();
{tabs.map((tab, i) => (
<button
key={i}
onClick={() => changeTab(i)}
className={`flex-1 p-2 text-center ${index === i ? 'border-b-2 border-gray-500 font-semibold' : 'text-gray-500'}`}
>
{tab}
</button>
))}
{index === 0 && <MyInfo />}
{index === 1 && <MyPost />}
{index === 2 && <MyStatus />}
요약
useState로 탭 기능을 만들고, 커스텀 훅(useTabs)으로 분리하면 재사용성과 코드 가독성이 향상된다. 탭 상태 관리가 필요한 컴포넌트에서 간단히 적용 가능!
이처럼 간단한 탭 UI라도 커스텀 훅으로 분리하면 코드의 재사용성과 유지보수가 훨씬 쉬워진다. 추후 더 복잡한 탭 구조로 확장할 때도 기본 뼈대가 단단해지는 느낌이다.