특정 경로에 따라 다른 페이지로 이동할 수 있는 탭버튼을 만들어보자. 스타일링은 emotion를 사용했다.
interface를 자세히보면 다음과 같다.
tabNames: 탭의 이름들을 담은 문자열 배열
tabLinks: userId를 인자로 받아 탭의 링크를 반환하는 함수들의 배열
const { userId } = useParams<{ userId: string }>();
탭을 클릭하면 아래와 같은 경로들로 이동하게 할 것이다.
/playlist/userID
/playlist/userID/saved
/playlist/userID/liked
NavLink는 다음과 속성들을 가진다. NavLink는 isActive, isPending, isTransitioning 상태를 제공하여 쉽게 스타일링을 할 수 있도록 도와준다.
https://reactrouter.com/en/main/components/nav-link
to: NavLink가 연결할 경로를 나타낸다 (tabLinks 함수를 사용하여 생성)
className: 활성 상태에 따라 'active' 클래스를 추가한다
end: 첫 번째 탭에만 적용되어 정확한 경로 일치를 확인한다
end prop이 true로 설정된 경우, NavLink는 현재 URL이 정확히 해당 링크의 경로와 일치할 때만 "active" 상태가 된다. 최종 코드에서 end={index === 0}는 첫 번째 탭(index가 0인 탭)에만 end prop을 적용한다.
첫 번째 탭에 end를 사용함으로써, 이 탭이 다른 모든 하위 경로에서 활성화되는 것을 방지한다. 왜냐하면 위에서와 같이 첫번째 탭을 제외한 나머지 탭들은 하위 페이지기 때문이다.
/playlist/userID
/playlist/userID/saved
/playlist/userID/liked
즉 /playlist/123에서는 첫 번째 탭만 활성화되고, /playlist/123/saved에서는 두 번째 탭이 활성화된다.
/playlist/123/likes에서는 세 번째 탭이 활성화된다.
import React from 'react';
import { css } from '@emotion/react';
import { NavLink, useParams } from 'react-router-dom';
import colors from '@/constants/colors';
import { fontWeight } from '@/constants/font';
interface TabButtonProps {
tabNames: string[];
tabLinks: ((userId?: string) => string)[];
}
const TabButton: React.FC<TabButtonProps> = ({ tabNames, tabLinks }) => {
const { userId } = useParams<{ userId: string }>();
return (
<div css={tabContainerStyle}>
{tabNames.map((name, index) => (
<NavLink
key={name}
to={tabLinks[index](userId)}
css={tabLinkStyle}
className={({ isActive }) => (isActive ? 'active' : '')}
end={index === 0}
>
{name}
</NavLink>
))}
</div>
);
};
나는 tabLinks를 ROUTES에서 가져왔다.
<TabButton
tabNames={['마이플리', '저장된플리', '좋아요']}
tabLinks={[ROUTES.PLAYLIST, ROUTES.PLAYLIST_SAVED, ROUTES.PLAYLIST_LIKES]}
/>
const ROUTES = {
ROOT: '/',
SIGN_IN: '/signIn',
SIGN_UP: '/signUp',
HASH_TAG: '/hashTag',
POPULAR: '/popular',
FOLLOWING: '/following',
SEARCH: (searchText = ':searchText') => `/search/${searchText}`,
DETAIL: (playListId = ':playListId') => `/detail/${playListId}`,
FOLLOWER: (userId = ':userId') => `/follower/${userId}`,
PROFILE: (userId = ':userId') => `/profile/${userId}`,
PROFILE_MODIFY: (userId = ':userId') => `/profile/${userId}/modify`,
PROFILE_FOLLOWING: (userId = ':userId') => `/profile/${userId}/following`,
PLAYLIST: (userId = ':userId') => `/playlist/${userId}`,
PLAYLIST_SAVED: (userId = ':userId') => `/playlist/${userId}/saved`,
PLAYLIST_LIKES: (userId = ':userId') => `/playlist/${userId}/likes`,
PLAYLIST_ADD: (userId = ':userId') => `/playlist/${userId}/add`,
PLAYLIST_MODIFY: (userId = ':userId') => `/playlist/${userId}/modify`,
NOT_FOUND: '*',
};
export default ROUTES;