Mui
Tabs 공식문서
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
import * as React from 'react';
import Box from '@mui/material/Box';
import Tabs from '@mui/material/Tabs';
import Tab from '@mui/material/Tab';
import Typography from '@mui/material/Typography';
import {
MemoryRouter,
Route,
Routes,
Link,
matchPath,
useLocation,
} from 'react-router-dom';
import { StaticRouter } from 'react-router-dom/server';
function Router(props: { children?: React.ReactNode }) {
const { children } = props;
if (typeof window === 'undefined') {
return <StaticRouter location="/drafts">{children}</StaticRouter>;
}
return (
<MemoryRouter initialEntries={['/drafts']} initialIndex={0}>
{children}
</MemoryRouter>
);
}
function useRouteMatch(patterns: readonly string[]) {
const { pathname } = useLocation();
for (let i = 0; i < patterns.length; i += 1) {
const pattern = patterns[i];
const possibleMatch = matchPath(pattern, pathname);
if (possibleMatch !== null) {
return possibleMatch;
}
}
return null;
}
function MyTabs() {
// You need to provide the routes in descendant order.
// This means that if you have nested routes like:
// users, users/new, users/edit.
// Then the order should be ['users/add', 'users/edit', 'users'].
const routeMatch = useRouteMatch(['/inbox/:id', '/drafts', '/trash']);
const currentTab = routeMatch?.pattern?.path;
return (
<Tabs value={currentTab}>
<Tab label="Inbox" value="/inbox/:id" to="/inbox/1" component={Link} />
<Tab label="Drafts" value="/drafts" to="/drafts" component={Link} />
<Tab label="Trash" value="/trash" to="/trash" component={Link} />
</Tabs>
);
}
function CurrentRoute() {
const location = useLocation();
return (
<Typography variant="body2" sx= color="text.secondary">
Current route: {location.pathname}
</Typography>
);
}
export default function TabsRouter() {
return (
<Router>
<Box sx=>
<Routes>
<Route path="*" element={<CurrentRoute />} />
</Routes>
<MyTabs />
</Box>
</Router>
);
}
Tab 사용하기
- 단일 페이지로 만드려고 계획하던 중
Nav bar
에서 항목을 클릭했을 때, 항목에 연결된 컴포넌트를 보여주기 위한 탭이 필요했다. - 탭이나
Nav
에 관한 여러 항목을 찾아보던 중 내가 사용하고자 하는 디자인과 기능에 적합한 것이 Tab이었다. - 코드 설명은 다음과 같다.
- 탭에 해당하는 리스트를 정한다.(url명, ex: Home = Home)
- 리액트 라우터를 사용하여 주솟값이 변경될 떄마다 이에 해당하는 리스트의 탭과 일치시킨다.
- 탭을 클릭할 시에도 이에 해당하는 라우터로 연결한다.
- 위 방식은
Router
로 해당하는 컴포넌트 페이지로 연결하지만, 내가 필요한 것은 단일 페이지기 때문에 라우터를 제외하고 해당 탭을 클릭했을 때 클릭한 리스트와 일치하는id
를 가진 컴포넌트를 화면에 보여주기로 했다.
코드
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
const routeMatch = useRouteMatch(["/Home", "/About", "/Skills", "/Experience"]);
const currentTab = routeMatch;
const scrollHandler = (e: string) => {
document.getElementById(e)?.scrollIntoView({
behavior: "smooth",
});
};
return (
<Tabs
value={currentTab}
sx={
{
// "& .MuiTabs-indicator": { backgroundColor: "transparent" },
// "& .Mui-selected": { color: "purple" },
}
}
>
<Tab
key={list}
label={list.replace("/", "")}
value={"/" + list}
to={list}
component={Link}
onClick={() => scrollHandler(list)}
/>
</Tabs>
);
1
2
3
4
// Main.tsx
export default function Index() {
return <div id="Home">Example</div>;
}
Tab
의Home
을 클릭할 때 해당하는 아이디를 가진 컴포넌트로 scrollIntoView 할 수 있다.Tab
은Tabs
로 감싸져 있어야 하며,sx
로 해당 스타일을 지정한다.
2024-01-16
custom 시 props
1
2
3
4
5
6
7
8
9
10
11
12
13
14
import { styled } from "mui/material";
export default function Example() {
return (
<Tab
key={list}
label={list.replace("/", "")}
value={"/" + list}
to={list}
component={Link}
onClick={() => scrollHandler(list)}
/>
);
}
- 위 코드는 Mui code sande box에 나와있는 예제이다.
- 하지만 Mui Tab API에 들어가보면
to, component
속성이 없다. - Tab 컴포넌트를 커스텀 하려고 할 때, 문제가 발생했다.
1
2
3
4
5
6
7
8
9
10
11
12
return (
<TabList
key={list}
label={list.replace("/", "")}
value={"/" + list}
to={list} // error
component={Link} // error
onClick={() => scrollHandler(list)}
/>
);
const TabList = styled(Tab)({});
- 위처럼 커스텀 시 에러가 발생했는데, 이는
Tab API
에 나와있는 속성대로 기본적으로 제공되는 속성이 아니기에 에러가 생긴 것이다. - 커스텀 시에만 에러가 발생한 이유는, 커스텀 시에는
Tab
의 기본 속성만을 사용되기에 속성을 추가적으로 작성해줘야 했다.
1
2
3
4
5
6
7
8
type TabCustomPropsType = {
to: string;
component: React.ForwardRefExoticComponent<LinkProps & React.RefAttributes<HTMLAnchorElement>>;
}
const TabList = styled(Tab)<TabCustomPropsType>({
...
})