ㅇㅇㅈ Blog

프론트엔드 수행중

0%

Material-ui 따라 해보기

Material-ui 따라 해보기

1
2
3
4
5
$ yarn create vite
..
$ yarn

react-ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// App.tsx

import Header from './components/Header';
import Nav from './components/Nav';
import Article from './components/Article';
function App() {
return (
<>
<Header />
<Nav />
<Article />
</>
);
}
export default App;

간단한 컴포넌트를 만들고 임포트

mui 설치

https://mui.com/material-ui/getting-started/installation/

mui는 기본으로 emotion을 사용한다 근데 styled-component도 사용 할 수 있다
그래서 styled-components 도 함께 설치

1
$ yarn add @mui/material @mui/styled-engine-sc styled-components

설치 후 article 컴포넌트에서 button을 만들어 보았다

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import React from 'react';
import { Button } from '@mui/material';
const Article = () => {
return (
<div>
<article>
<h2>Welcome</h2>
Hello Web!
<br />
</article>
<Button variant='contained'>Text</Button>
</div>
);
};

export default Article;

Button 을 mui/material 에서 임포트후 컴포넌트 처럼 사용 하는 것

error..

저렇게 하고 렌더링을 하면 무한 로딩이 되면서 터미널에 에러가 잔뜩 뜬다

대충 보니 자세히는 몰라도 emotion이 안깔려 있어서 에러를 내뱉는거 같다

찾아보니 mui는 기본적으로 emotion을 사용하기 때문에 styled-components를 사용할려면 추가 설정을 해줘야 한다

https://mui.com/material-ui/guides/styled-engine/

가이드가 꽤 친절하게 되어있다 그냥 따라서 package.json 에 resolutions를 추가해주고

1
2
3
4
5
6
7
8
9
10
"dependencies": {
...

"@mui/styled-engine-sc": "^5.8.0",

},
// 아래는 추가 되는 부분
"resolutions": {
"@mui/styled-engine-sc": "^5.8.0"
}

이 프로젝트는 vite로 설치해서 webpack.config 대신
vite.config에 작성

1
2
3
4
5
6
7
8
9
10
 module.exports = {
//resolve 부분을 추가해준다
resolve: {
alias: {
'@mui/styled-engine': '@mui/styled-engine-sc'
},
},
};
Copy

tsconfig.jsoncompilerOptionspaths를 추가 해줬더니 잘 된다

1
2
3
4
5
6
7
{
"compilerOptions": {
"paths": {
"@mui/styled-engine": ["./node_modules/@mui/styled-engine-sc"]
}
},
}

Button

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import React from 'react';
import { Button } from '@mui/material';
const Article = () => {
return (
<div>
<article>
<h2>Welcome</h2>
Hello Web!
<br />
</article>
<Button variant='contained'>Text</Button>
</div>
);
};

export default Article;

Button variant 값에 따라 모양이 달라진다

https://mui.com/material-ui/react-button/

Button들을 그룹시켜 줄 수도 있다

1
2
3
4
5
<ButtonGroup variant='outlined'>
<Button>Create</Button>
<Button>Update</Button>
</ButtonGroup>
<Button variant='outlined'>Delete</Button>

create와update 버튼이 그룹화 되어 묶여 있다

Container

웹 사이트의 base width를 Container를 통해 만들어 줄 수 있다

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// App.tsx

import { Container } from '@mui/material';
function App() {
return (
<>
<Container fixed>
<Header />
<Nav />
<Article />
</Container>
</>
);
}

App.tsx 에서 import 한 Container 컴포넌트로 다른 컴포넌트들을 감싸주었다

컨텐츠들이 margin auto를 준 것 처럼 중앙에 있게 되고,
또한 반응형으로 동작하게 된다

Grid

mui 그리드 시스템을 통해 유연한 레이아웃을 만들 수 있다

가로를 12등분한 column을 가지고 각 컨테츠가 12개의 column중 몇 칸을 차지 할 것인지를 설정 해주면 된다

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// App.tsx

import Header from './components/Header';
import Nav from './components/Nav';
import Article from './components/Article';
import { Container, Grid } from '@mui/material';
function App() {
return (
<>
<Container fixed>
<Header />
<Grid container spacing={2}>
<Grid item xs={2} md={6} lg={10}>
<Nav />
</Grid>
<Grid item xs={10} md={6} lg={2}>
<Article />
</Grid>
</Grid>
</Container>
</>
);
}

Grid를 설정할 컴포넌트 NavArticle<Grid container>로 감싸 준 뒤
각각의 컴포넌트를 <Grid item>으로 다시 감싸 준다.
item이 grid에는 breakpoint마다 몇 칸을 차지 할 것인지를 넣어 주면 된다.

breakPoint

mui breakpoint
sm는 600px ~ 이상일때
md는 900px ~ 이상일때 뭐 이런식이다

그래서 위 코드를 보면 브라우저가 lg일때 10칸 ,2칸 비율로 컨텐츠를 배치한다

breakpoint가 md일때 6:6 으로 컨텐츠가 배치된다

Dialog

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
import React, { useState } from 'react';
import {
Button,
ButtonGroup,
Dialog,
DialogActions,
DialogContent,
DialogTitle,
DialogContentText,
} from '@mui/material';

const Article = () => {
return (
<article>
<h2>Welcome</h2>
Hello Web!
<br />
<br />
<br />
<ButtonGroup variant='outlined'>
<Button >
Create
</Button>
<Button>Update</Button>
</ButtonGroup>
<Button variant='outlined'>Delete</Button>
<Dialog open={true}>
hi
</Dialog>
</article>
);
};

export default Article;

Dialog 를 import 하고 버튼 밑에 추가
Dialog는 독립적으로 사용되기 때문에 아무대나 작성해도 상관은 없다
prop으로 open={true} 를 주고 보면 화면에 검게 변한다

Dialog에는 따로 레이아웃 영역을 잡아주는? 컴포넌트들이 있다

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

import React, { useState } from 'react';
import {
Button,
ButtonGroup,
Dialog,
DialogActions,
DialogContent,
DialogTitle,
DialogContentText,
} from '@mui/material';

const Article = () => {
return (
<article>
<h2>Welcome</h2>
Hello Web!
<br />
<br />
<br />
<ButtonGroup variant='outlined'>
<Button >
Create
</Button>
<Button>Update</Button>
</ButtonGroup>
<Button variant='outlined'>Delete</Button>
<Dialog open={true}>
<DialogTitle>Hello</DialogTitle>
<DialogContent>
<DialogContentText>
Lorem ipsum dolor sit amet consectetur, adipisicing elit. Nulla
deleniti quae tenetur voluptates eum, alias commodi optio eligendi
repellendus sed blanditiis, suscipit ipsa, possimus ex. Asperiores
hic assumenda est illo. Lorem ipsum dolor sit amet consectetur,
adipisicing elit. Nulla deleniti quae tenetur voluptates eum, alias
commodi optio eligendi repellendus sed blanditiis, suscipit ipsa,
possimus ex. Asperiores hic assumenda est illo. Lorem ipsum dolor
sit amet consectetur, adipisicing elit. Nulla deleniti quae tenetur
voluptates eum, alias commodi optio eligendi repellendus sed
blanditiis, suscipit ipsa, possimus ex. Asperiores hic assumenda est
illo. Lorem ipsum dolor sit amet consectetur, adipisicing elit.
Nulla deleniti quae tenetur voluptates eum, alias commodi optio
eligendi repellendus sed blanditiis, suscipit ipsa, possimus ex.
Asperiores hic assumenda est illo.
</DialogContentText>
<DialogActions>
<Button>Create</Button>
<Button>CANCEL</Button>
</DialogActions>
</DialogContent>
</Dialog>
</article>
);
};

export default Article;

DialogTitle, DialogContent안에 DialogContentText, DialogActions

각각이 무슨 기능이 있는거 같지는 않다 그냥 레이아웃 잡는 정도?

Button을 감싸고 있는 DialogActions를 지워도 Button은 잘 작동한다.
다만 레이아웃을 따로 잡아줘야 할 뿐..

Dialog를 키고 닫을려면 open의 true/false 값을 state로 관리 해주면 된다

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
const Article = () => {
const [open, setOpen] = useState(false);
return (
<article>
<h2>Welcome</h2>
Hello Web!
<br />
<br />
<br />
<p>
Lorem ipsum dolor sit amet consectetur, adipisicing elit. Nulla deleniti
quae tenetur voluptates eum, alias commodi optio eligendi repellendus
sed blanditiis, suscipit ipsa, possimus ex. Asperiores hic assumenda est
illo. Lorem ipsum dolor sit amet consectetur, adipisicing elit. Nulla
deleniti quae tenetur voluptates eum, alias commodi optio eligendi
repellendus sed blanditiis, suscipit ipsa, possimus ex. Asperiores hic
assumenda est illo. Lorem ipsum dolor sit amet consectetur, adipisicing
elit. Nulla deleniti quae tenetur voluptates eum, alias commodi optio
eligendi repellendus sed blanditiis, suscipit ipsa, possimus ex.
Asperiores hic assumenda est illo. Lorem ipsum dolor sit amet
consectetur, adipisicing elit. Nulla deleniti quae tenetur voluptates
eum, alias commodi optio eligendi repellendus sed blanditiis, suscipit
ipsa, possimus ex. Asperiores hic assumenda est illo.
</p>
<ButtonGroup variant='outlined'>
<Button
onClick={() => {
setOpen(true);
}}
>
Create
</Button>
<Button>Update</Button>
</ButtonGroup>
<Button variant='outlined'>Delete</Button>
<Dialog open={open}>
<DialogTitle>Hello</DialogTitle>
<DialogContent>
<DialogContentText>
Lorem ipsum dolor sit amet consectetur, adipisicing elit. Nulla
deleniti quae tenetur voluptates eum, alias commodi optio eligendi
repellendus sed blanditiis, suscipit ipsa, possimus ex. Asperiores
hic assumenda est illo. Lorem ipsum dolor sit amet consectetur,
adipisicing elit. Nulla deleniti quae tenetur voluptates eum, alias
commodi optio eligendi repellendus sed blanditiis, suscipit ipsa,
possimus ex. Asperiores hic assumenda est illo. Lorem ipsum dolor
sit amet consectetur, adipisicing elit. Nulla deleniti quae tenetur
voluptates eum, alias commodi optio eligendi repellendus sed
blanditiis, suscipit ipsa, possimus ex. Asperiores hic assumenda est
illo. Lorem ipsum dolor sit amet consectetur, adipisicing elit.
Nulla deleniti quae tenetur voluptates eum, alias commodi optio
eligendi repellendus sed blanditiis, suscipit ipsa, possimus ex.
Asperiores hic assumenda est illo.
</DialogContentText>
<DialogActions>
<Button>Create</Button>
<Button
onClick={() => {
setOpen(false);
}}
>
CANCEL
</Button>
</DialogActions>
</DialogContent>
</Dialog>
</article>
);
};

export default Article;

생각보다 사용법이 쉽다.. 많이 사용하게 될거 같다